#include "STLUse.h"
#include <algorithm>
#include <functional>
#include <iostream>
#include <stack>
#include <string>
#include <vector>


void show_demo()
{
    stack_demo();
    adapter_demo();
    search_demo();
}

// 概述
void summarize()
{
    // 1.STL: 容器、算法、迭代器、仿函数、适配器、空间配置器。

    // 2.容器
    //   (1)顺序容器: vector[动态数组]、deque[双向队列]、list[双向链表]
    //   (2)关联容器:set/multiset[集合]、map/multimap[字典]
    //   (3)容器适配器<从deque封装>:stack[栈]、queue[队列]、priority_queue[优先级队列]

    // 3.各容器简介
    //   (1)vector: 内存连续。
    //   (2)deque: 内存连续,在两端增删具有较佳的性能。
    //   (3)list: 内存不连续,不随机存取。
    //   (4)集合带 multi 的,允许 key 重复。

    // 4.map hashtable deque list实现原理
    //   (1)map: 内部是红黑树实现,可以自动排序,因此内部元素是有序的。
    //   (2)hashtable: 函数映射的思想记录存储位置和关键字。
    //   (3)deque: 内部实现是双向队列。
    //   (4)list: 内部实现是双向链表。

    // 5.容器操作复杂度
    //   (1)vector,插入[O(N)]、查看[O(1)]、删除[O(N)]。
    //   (2)deque,插入[O(N)]、查看[O(1)]、删除[O(N)]。
    //   (3)list,插入[O(1)]、查看[O(N)]、删除[O(1)]。
    //   (4)map、set、multiset、multimap<红黑树,平衡二叉树>,插入[O(logN)]、查看[O(logN)]、删除[O(logN)]。
    //   (5)unordered_map、unordered_set、unordered_multimap、
    //   unordered_multiset:
    //      插入:O(1),最坏O(N)
    //      查看:O(1),最坏O(N)
    //      删除:O(1),最坏O(N)

    // x.空间适配器
}

void stack_demo()
{
    std::stack<SimuData> stack{};

    // 不提供遍历行为
    SimuData da{};
    da.data_ = 89;
    da.value_ = 5.2;

    stack.push(da);

    while (!stack.empty()) {
        std::cout << stack.top().data_ << std::endl;
        stack.pop();   // 出栈
    }
}

void queue_demo()   // 队列
{
    // 无迭代器
}

void list_demo()
{
    // 双向循环链表
    // 性质:插入删除操作不会造成原有的迭代器实现,vector 不行。
}

void set_demo()
{
    // 特性:key 会被自动排序,不允许有重复的值。
    // set 的 iterator 是一种 const_iterator,因为 set的元素值就是
    // 键值,关系到 set 元素的排序规则。
}

void multi_set_demo()
{
    // 与 set 特性用法一致。差别在于可以key重复。
    // 与 set 一样底层实现使用的是红黑树。
}

// binary_function 指二元 (这个函数被标记了 弃用)
// class A : public std::binary_function<int, int, void> 
// {
// public:
//     void operator()(int val, int start) const
//     {
//         std::cout << "val:" << val << " start:" << start
//                   << " total:" << val + start << "\n";
//     }
// };

// 取反适配器 (unary_function 这个函数被标记了 弃用)
// class MGreator : public std::unary_function<int, bool>
// {
// public:
//     bool operator()(int val) const
//     {
//         // 大于 3
//         return val > 3;
//     }
// };

void my_print(int val) { std::cout << val << std::endl; }
void my_print2(int val, int start)
{
    std::cout << val << " " << start << std::endl;
}

class Person
{
public:
    Person(std::string name, int age)
    {
        name_ = name;
        age_ = age;
    }
    void print()
    {
        std::cout << age_ << " ";
        std::cout << name_ << "\n";
    }
    std::string name_{};
    int         age_{};
};

void my_print3(const Person& person)
{
    std::cout << person.age_ << " ";
    std::cout << person.name_ << "\n";
}

// 仿函数的目的:协助算法完成不同的策略。
void adapter_demo()
{
    std::vector<int> vec{};
    vec.push_back(1);
    vec.push_back(2);
    vec.push_back(3);
    vec.push_back(4);
    vec.push_back(5);

    // bind2nd 将45绑定到第二个参数, bind1st 将45绑定到第一个参数
    // 《函数对象适配器》  (bind2nd 这个函数被标记了 弃用)
    // std::for_each(vec.begin(), vec.end(), std::bind2nd(A(), 45));

    // std::vector<int>::iterator iter =
    //     std::find_if(vec.begin(), vec.end(), MGreator());
    // if (iter != vec.end()) {
    //     // 找到 *iter
    //     std::cout << *iter << std::endl;
    // }
    //  (not1 ==> 一元的取反)
    // iter = std::find_if(vec.begin(), vec.end(), std::not1(MGreator()));
    // if (iter != vec.end()) {
    //     // 找到 *iter
    //     std::cout << *iter << std::endl;
    // }

    // 这是另一个示例 deprecated-declarations (bind2nd 这个函数被标记了 弃用)
    // iter = std::find_if(vec.begin(), vec.end(),
    //                     std::not1(std::bind2nd(std::greater<int>(), 3)));
    // if (iter != vec.end()) {
    //     // 找到 *iter
    //     std::cout << *iter << std::endl;
    // }

    // 《函数适配器》
    std::for_each(vec.begin(), vec.end(), my_print);
    // 将函数指针适配成函数的对象 ptr_fun (bind2nd ptr_fun 这个函数被标记了 弃用)
    // std::for_each(vec.begin(), vec.end(),
    //               std::bind2nd(std::ptr_fun(my_print2), 1000));

    // 《成员函数适配器》
    std::vector<Person> pvec{};
    pvec.emplace_back("A", 1);
    pvec.emplace_back("B", 2);
    pvec.emplace_back("C", 3);
    pvec.emplace_back("D", 4);
    pvec.emplace_back("E", 5);
    std::for_each(pvec.begin(), pvec.end(), my_print3);

    // 利用 mem_fun_ref 适配一下。  (mem_fun_ref 这个函数被标记了 弃用)
    // std::for_each(pvec.begin(), pvec.end(), std::mem_fun_ref(&Person::print));
}

// 常用查找算法
void search_demo()
{
    std::vector<int> demo{};
    demo.push_back(23);
    demo.push_back(21);
    demo.push_back(87);
    demo.push_back(11);
    demo.push_back(11);
    demo.push_back(6);
    demo.push_back(90);

    // find 直接按照值去查找
    std::vector<int>::iterator iter = std::find(demo.begin(), demo.end(), 11);
    if (iter != demo.end()) {
        std::cout << *iter << std::endl;
    }
    // find_if 使用你提供的条件去查找
    // 同理 count 和 count_if 也是如此。

    // adjacent_find   查找相邻的重复元素
    iter = std::adjacent_find(demo.begin(), demo.end());
    if (iter != demo.end()) {
        std::cout << "相邻的重复元素:" << *iter << std::endl;
    }

    // binary_search 二分查找法,需要有序。
}

void predicate_demo()
{
    // 谓词是指普通函数或重载的operator(返回值是bool类型的函数对象(仿函数)
}

void traverse_demo()
{
    // 遍历算法
    // transform 用于搬运
}

// 排序
void sort_demo()
{
    // merge 合并,两个容器需要有序
    // sort 排序
    // random_shuffle 随机调整次序
    // reverse 翻转
}

// 集合算法
void set_algorithm_demo()
{
    // set_intersection 求交集
    // set_unin 求并集
    // set_difference 差集
}