04.08_111期_C++_reverseiterator实现和理解

发布于:2024-04-14 ⋅ 阅读:(160) ⋅ 点赞:(0)

    priority_queue这个类中的top()获得的是数据较大的优先级高,
    priority_queue其底层实现就是一个大根堆
    priority_queue<int> pq;
    传入以下的模板参数,其中 greater<int> 保证了 生成的 pq 对象是小根堆
    greater<int>为仿函数

    vector<int> v = { 3, 1, 7, 4, 6, 3 };
    //升序
    sort(v.begin(), v.end());
    for (auto e : v)
    {
        cout << e << " ";
    }
    cout << endl;

    降序: 要借助仿函数greater<int>,可以使用几种方法
    第一种:使用具体的实例化对象
    greater<int> gt;
    sort(v.begin(), v.end(), gt);

    第二种 匿名对象
    这里之所以使用了greater<int>()创建一个属于  greater<int>类  的匿名对象
    是因为sort是一个函数,其参数的类型都是函数模板给出的,所以传入参数时要给确切的实例化对象

 仿函数就是一个普通的类
 这个类创建出来的实例可以像函数名一样,对()内进行传实参后使用

    这个类对()这个运算符进行重载,使得下面两种用法相等
        1. 实例化对象.operator()(参数1, 参数2, ...)
        2. 实例化对象(参数1, 参数2, ...)

    priority_queue这个类中的top()获得的是数据较大的优先级高,
    priority_queue其底层实现就是一个大根堆
    priority_queue<int> pq;
    传入以下的模板参数,其中 greater<int> 保证了 生成的 pq 对象是小根堆
    greater<int>为仿函数
    下面三种push元素的方式:
    方式一:先创建一个Date的实例,再用这个实例进行push
    方式二:生成一个匿名对象之后,将这个匿名对象进行push
    方式三:隐式类型转换,生成临时对象之后,将这个匿名对象进行push

    为什么以下函数给第三个位置直接传了一个 名叫GreaterPDate的形参
        1. 如果直接传入bit::greater<Date*>,
           是无法调到bool Date::operator>(const Date& d) const 这个函数的
           因为Compare com; 这句话实际上是执行了 greater<Date*> com;这句话
           com(_con[parent], _con[child]); 这句话实际上就执行了 greater类中的函数 operator()
            而且传入参数时是执行
          bool operator()(const Date* x, const Date* y)
            {
                return x > y;
            }
            以上函数在执行到 return x > y; 这句话时
            那么就要调用 Date类中的 operator> 这个函数,对应执行的是
            可此时的函数的形参类型是 const Date& 类型,不是const (Date*)& d 类型
        2. 在main函数上方直接定义一个函数,如果函数声明是 
            σ:bool operator<(const Date* d1, const Date* d2);    同样不能使用
           bit::priority_queue<Date*, vector<Date*>, bit::greater<Date*>> pqptr;这句话
           因为无论什么类型,只要加上了 * 号,就变成了指针类型的变量,
           就一定是一个内置类型的变量,那么σ处的声明就完全没有用到自定义类型
           此时的运算符重载就不符合语法规定,
           语法规定要对 >, <, ==, != 这一类的逻辑运算符进行重载时,
           声明的参数列表中至少要有一个自定义类型的参数
      3. 如果非要在优先级队列中传入Date*作为模板参数,只能使用仿函数的方法
           在优先级队列的逻辑中不像 2. 那样去重新重载专门属于Date* 的比较逻辑
           而是通过com这个实例对应的类是一个如下的仿函数
           其中   return *p1 > *p2;   这句话中的 > 还是
           调用了Date这个类中的bool Date::operator>(const Date& d) const这个函数


            class GreaterPDate
            {
            public:
                bool operator()(const Date * p1, const Date * p2)
                {
                    return *p1 > *p2;
                }
            };
           而在执行到com(_con[parent], _con[child])这个代码
           可以通过GreaterPDate这个类中对 () 进行重载的操作符 
           即通过这个运算符调用bool operator()(const Date * p1, const Date * p2)这个函数

           通过上面的分析可知,仿函数可以在函数要执行不同的逻辑时调用不同的函数
           priority_queue是容器适配器,只是与stack, queue 这另外两种适配器不同的是,
           priority_queue还需要仿函数参数控制大根堆和小根堆

    bit::queue<int> st;
    st.push(1);
    st.push(2);
    st.push(3);
    st.push(4);
    st.push(5);
    printf("size: %d\n", st.size());
    for (size_t i = 0; !st.empty(); i++)
    {
        if (!st.empty())
        {
            cout << st.front() << " ";
            st.pop();
        }
    }
    cout << endl;

    Less<int> ls;
    下面这几句话是等价的
    cout << ls(1, 2) << endl;
    cout << ls.operator()(1, 2) << endl;
    cout << Less<int>()(1, 2) << endl;
    cout << Less<int>().operator()(1, 2) << endl;

这个文件σ设计一个对应任意容器的反向迭代器
 也就是迭代器适配器
 既然是适配器,那么只要模板参数确定,这个适配器类就要有对应的属性
 这样就不用在每个容器类的内部专门都定义一个反向迭代器的行为了
 每个容器要使用  反向迭代器  都是调用σ中的迭代器类,
 然后调用文件σ中对应的反向迭代器
 而这个  反向迭代器类  中的所有运算符重载成员函数
        都是调用  正向迭代器  的类中的已经重载过的运算符

    ReverseIterator这个类在实现时要达到的效果是:
    只要有一个具体的容器类的正向迭代器,就能获得属于这个容器类的 反向迭代器
    比如给 list<T>::iterator,经过这个类就得到 list<T>::ReverseIterator
    在STL中实现的形式就是:
    typedef __list_iterator<T, T&, T*> iterator;
    typedef __list_iterator<T, const T&, const T*> const_iterator;
    typedef reverse_iterator<iterator> reverse_iterator;
    typedef reverse_iterator<const_iterator> const_reverse_iterator;


网站公告

今日签到

点亮在社区的每一天
去签到