【C++】C++ STL探索:Priority Queue与仿函数的深入解析(二)

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 【C++】C++ STL探索:Priority Queue与仿函数的深入解析

【C++】C++ STL探索:Priority Queue与仿函数的深入解析(一)https://developer.aliyun.com/article/1617382


2.3 仿函数相较于普通函数优势

虽然普通函数在大多数情况下足够,但仿函数提供了更强大的功能和灵活性。

仿函数的优势

  • 仿函数是模板编程的重要组成部分,可以与模板一起使用,实现泛型编程的目的。
  • 将逻辑和数据封装在一个类中,并且可以轻松调整或扩展仿函数的行为,而不需要改变其调用接口
  • 仿函数可以将复杂逻辑和数据封装在类对象中,使得代码更加模块化和可维护,重点体现在封装。
  • 仿函数可以有成员变量,在不同的调用之间保持状态。
  • 每个仿函数都有不同的类去封装,也可以更好适应泛型编程,灵活地去调整

通过一个类来控制这里的比较逻辑,并且内置类型与自定义类型都支持这种做法。

2.4 当T为指针类型

class Date
{
public:
  friend ostream& operator<<(ostream& _cout, const Date& d);
  Date(int year = 1900, int month = 1, int day = 1)
    : _year(year)
    , _month(month)
    , _day(day)
  {}
  bool operator<(const Date& d)const
  {
    return (_year < d._year) ||
      (_year == d._year && _month < d._month) ||
      (_year == d._year && _month == d._month && _day < d._day);
  }
  bool operator>(const Date& d)const
  {
    return (_year > d._year) ||
      (_year == d._year && _month > d._month) ||
      (_year == d._year && _month == d._month && _day > d._day);
  }
private:
  int _year;
  int _month;
  int _day;
};
ostream& operator<<(ostream& _cout, const Date& d)
{
  _cout << d._year << "-" << d._month << "-" << d._day;
  return _cout;
}
int main()
{
  priority_queue <Date*, vector<Date*>, greater<Date*>> pqptr;
  pqptr.push(new Date(2024, 4, 14));
  pqptr.push(new Date(2024, 4, 11));
  pqptr.push(new Date(2024, 4, 15));
  while (!pqptr.empty())
  {
    cout << *(pqptr.top()) << " ";
    pqptr.pop();
  }
  cout << endl;
  return 0;
}

结果说明:正如图中问题,多次运行出现的结果是不同的,导致这种情况的原因是因为地址的大小new出来是随机的,这里如果是单纯的比较大小,只是比较地址编号的大小,而不是比较日期的大小。这里没有对*进行重载,对此需要单独写。

解决措施

class GteaterDate
{
    public:
    bool operator()(const Date* p1, const Date* p2)
    {
        return *p1 > *p2;
    }
};

在类名实现比较指针的可调用函数对象(仿函数控制比较逻辑,控制任何比较)在优先级队列参数部分传递。

2.5 仿函数解决实际问题

场景如下:

假如我这里有一堆商品,我需要某个商品的排序,但是这里对于实际中需要排序的类型不止一种,那么如果需要看不同类型的排序,就需要修改,如何破局只有大于或者小于,但是总不能说"请稍等,程序员正在改代码"吧!对此需要使用仿函数的配合,模板帮我们控制的是类型不同的类型。

struct Goods
{
    string _name; // 名字
    double _price; // 价格
    int _evaluate; // 评价
    Goods(const char* str, double price, int evaluate)
        :_name(str)
            , _price(price)
            , _evaluate(evaluate)
        {}
};
struct ComparePriceLess
{
    bool operator()(const Goods& gl, const Goods& gr)
    {
        return gl._price < gr._price;
    }
};
struct ComparePriceGreater
{
    bool operator()(const Goods& gl, const Goods& gr)
    {
        return gl._price > gr._price;
    }
};
struct CompareEvaluateLess
{
    bool operator()(const Goods& gl, const Goods& gr)
    {
        return gl._evaluate < gr._evaluate;
    }
};
struct CompareEvaluateGreater
{
    bool operator()(const Goods& gl, const Goods& gr)
    {
        return gl._evaluate > gr._evaluate;
    }
};
int main()
{
    vector<Goods> v = { { "苹果", 2.1, 5 }, { "香蕉", 3, 4 }, { "橙子", 2.2,
                                                           3 }, { "菠萝", 1.5, 4 } };
    sort(v.begin(), v.end(), ComparePriceLess());
    sort(v.begin(), v.end(), ComparePriceGreater());
    sort(v.begin(), v.end(), CompareEvaluateLess());
    sort(v.begin(), v.end(), CompareEvaluateGreater());
}

注意:有些容器是没有迭代器的,这样子话就会破坏某种特性,一般不提供

三、反向迭代器

反向迭代器本质是写一个反向迭代器的类模板,给编译器传不同的容器的正向迭代器实例化,编译器帮助我们实例化出各种容器的对应反向迭代器。

3.1 反向与正向迭代器不同点

从功能上是类似的,但是运算符重载++与–运算符行为相反的。

同时反向与迭代器起始位置和结束位置是相反的,库里面也是形成对称,但是不是绝对的,如果满足反向迭代器逻辑就行。

思考:

这里it.rbegin()指向的位置(it.end)是哨兵位的位置,我们不希望访问到哨兵位的位置

解决办法:

需要注意:

这里++不是正向迭代器++运算符重载的逻辑,而是–的逻辑,因为是反向迭代器。这里是不支持tmp-1的,tmp是自定义类型,而没有-的运算符重载。


【C++】C++ STL探索:Priority Queue与仿函数的深入解析(三)https://developer.aliyun.com/article/1617384

相关文章
|
1月前
|
存储 算法 C++
C++ STL 初探:打开标准模板库的大门
C++ STL 初探:打开标准模板库的大门
91 10
|
1月前
|
安全 Java 程序员
Collection-Stack&Queue源码解析
Collection-Stack&Queue源码解析
80 0
|
14天前
|
自然语言处理 编译器 Linux
|
19天前
|
自然语言处理 编译器 Linux
告别头文件,编译效率提升 42%!C++ Modules 实战解析 | 干货推荐
本文中,阿里云智能集团开发工程师李泽政以 Alinux 为操作环境,讲解模块相比传统头文件有哪些优势,并通过若干个例子,学习如何组织一个 C++ 模块工程并使用模块封装第三方库或是改造现有的项目。
|
1月前
|
存储 搜索推荐 C++
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器2
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器
48 2
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器2
|
30天前
|
存储 程序员 C++
C++常用基础知识—STL库(2)
C++常用基础知识—STL库(2)
67 5
|
29天前
|
存储 算法 调度
【C++打怪之路Lv11】-- stack、queue和优先级队列
【C++打怪之路Lv11】-- stack、queue和优先级队列
30 1
|
30天前
|
存储 自然语言处理 程序员
C++常用基础知识—STL库(1)
C++常用基础知识—STL库(1)
52 1
|
1月前
|
设计模式 存储 C++
C++之stack 和 queue(下)
C++之stack 和 queue(下)
31 1
|
1月前
|
算法 安全 Linux
【C++STL简介】——我与C++的不解之缘(八)
【C++STL简介】——我与C++的不解之缘(八)

推荐镜像

更多