C++仿函数的介绍以及priority_queue的介绍和模拟实现

打印 上一主题 下一主题

主题 1711|帖子 1711|积分 5133

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
目录
1.仿函数
1.1仿函数的介绍
1.2自定义类型利用仿函数 
1.3自定义支持比力巨细,但是比力的逻辑不是自己想要的逻辑
 2.优先级队列priority_queue
2.1priority_queue的介绍
2.2priority_queue的利用
2.3priority_queue的模拟实现 


1.仿函数

1.1仿函数的介绍

        仿函数的本质是一个类模板,只是这个类重载了operator(),以是当利用一个它的对象时看起来像利用和函数一样,以是被称为仿函数。
        下面通过仿函数的形式来写一个小于和大于的比力:
  1. #include <iostream>
  2. using namepsace std;
  3. template<class T>
  4. class Less
  5. {
  6. public:
  7.         bool operator()(const T& x, const T& y)
  8.         {
  9.                 return x < y;
  10.         }
  11. };
  12. template<class T>
  13. class Greater
  14. {
  15. public:
  16.         bool operator()(const T& x, const T& y)
  17.         {
  18.                 return x > y;
  19.         }
  20. };
  21. int main()
  22. {
  23.         Less<int> less_func;
  24.         Greater<int> greater_fun;
  25.         int a = 5;
  26.         int b = 10;
  27.         cout << less_func(a, b) << endl;
  28.         cout << greater_fun(a, b) << endl;
  29.         return 0;
  30. }
复制代码

1.2自定义类型利用仿函数 

        自定义类型必要利用仿函数进行比力时,必要在自定义类型内里提供<和>等比力运算符的重载。比方对日期类进行比力:
  1. #include <iostream>
  2. using namespace std;
  3. template<class T>
  4. class Less
  5. {
  6. public:
  7.         bool operator()(const T& x, const T& y)
  8.         {
  9.                 return x < y;
  10.         }
  11. };
  12. template<class T>
  13. class Greater
  14. {
  15. public:
  16.         bool operator()(const T& x, const T& y)
  17.         {
  18.                 return x > y;
  19.         }
  20. };
  21. class Date
  22. {
  23.         friend ostream& operator<<(ostream& _cout, const Date& d);
  24. public:
  25.         Date(int year = 1900, int month = 1, int day = 1)
  26.                 : _year(year)
  27.                 , _month(month)
  28.                 , _day(day)
  29.         {}
  30.         bool operator<(const Date& d)const
  31.         {
  32.                 return (_year < d._year) ||
  33.                         (_year == d._year && _month < d._month) ||
  34.                         (_year == d._year && _month == d._month && _day < d._day);
  35.         }
  36.         bool operator>(const Date& d)const
  37.         {
  38.                 return (_year > d._year) ||
  39.                         (_year == d._year && _month > d._month) ||
  40.                         (_year == d._year && _month == d._month && _day > d._day);
  41.         }
  42. private:
  43.         int _year;
  44.         int _month;
  45.         int _day;
  46. };
  47. int main()
  48. {
  49.         Less<Date> less_func;
  50.         Greater<Date> greater_func;
  51.         Date d1(2024, 9, 10);
  52.         Date d2(2024, 8, 15);
  53.         cout << less_func(d1, d2) << endl;
  54.         cout << greater_func(d1, d2) << endl;
  55.         return 0;
  56. }
复制代码

 1.3自定义支持比力巨细,但是比力的逻辑不是自己想要的逻辑

         这个时候仿函数必要我们自己进行重新,比如想通过比力日期类的指针进行日期的比力时,就必要将仿函数写成下面这个样子:
  1. #include <iostream>
  2. using namespace std;
  3. class DateLess
  4. {
  5. public:
  6.         bool operator()(Date* p1, Date* p2)
  7.         {
  8.                 return *p1 < *p2;
  9.         }
  10. };
  11. //日期类参考上一个代码中的日期类
  12. int main()
  13. {
  14.         Date d1(2024, 9, 10);
  15.         Date d2(2024, 8, 15);
  16.         Date* p1 = &d1;
  17.         Date* p2 = &d2;
  18.         DateLess func;
  19.         cout << func(p1, p2) << endl;
  20.         cout << func(p2, p1) << endl;
  21.         return 0;
  22. }
复制代码

 2.优先级队列priority_queue

2.1priority_queue的介绍

        priority_queue的文档介绍
1.优先队列是一种容器适配器,根据严格的弱排序标准,它的第一个元素总是它所包含的元素中最大的。priority_queue包含在queue这个头文件中。
2.雷同于堆,在堆中可以随时插入元素,而且只能检索最大堆元素(优先队列中位于顶部的元素)。在这内里(堆的介绍)中可以进行对堆的了解。
3.底层容器可以是任何标准容器类模板,也可以是其他特定计划的容器类。容器应该可以通过随机访问迭代器访问,并支持以下操纵:
(1)empty():检测容器是否为空。
(2)size():返回容器中有效元素个数。
(3)front():返回容器中第一个元素的引用。
(4)push_back():在容器尾部插入元素。
(5)pop_back():删除容器尾部元素。
4.标准容器vector和deque满意这些需求。默认情况下,假如没有为特定的epriority_queue类实例化指定容器类,则利用vector。
5.必要支持随机访问迭代器,以便始终在内部保持堆布局。容器适配器通过在必要时自动调用算法函数make_heap(),push_heap()和pop_heap()来自动完成操纵。
2.2priority_queue的利用

        优先级队列默认利用vector作为其底层存储数据的容器,在vector上又利用dui算法将vector中元素构造成堆的布局,因此priority_queue就是堆,以是必要用到堆的位置,都可以考虑利用priority_queue。注意:默认情况下priority_queue是大堆

  1. #include <iostream>
  2. #include <vector>
  3. #include <queue>
  4. #include <functional>
  5. using namespace std;
  6. void test_priority_queue()
  7. {
  8.         // 默认情况下,创建的是大堆,其底层按照小于号比较
  9.         vector<int> v{3, 2, 7, 6, 0, 4, 1, 9, 8, 5};
  10.         priority_queue<int> q1;
  11.         for (auto& e : v)
  12.                 q1.push(e);
  13.         while(!q1.empty())
  14.         {
  15.                 cout << q1.top() << " ";
  16.                 q1.pop();
  17.         }
  18. }
  19. int main()
  20. {
  21.         test_priority_queue();
  22.         return 0;
  23. }
复制代码

        假如每次访问顶部元素时都访问的是最小元素,则必要建立小堆。利用的时候只必要把上述priority_queue<int> q1 改为 priority_queue<int, vector<int>, greater<int>>即可,默认大堆的情况下,给的仿函数是less<int>。
2.3priority_queue的模拟实现 

         优先级队列的存储布局就是一个堆,内里的向上调解算法(AdjustUp())和向下调解算法(AdjustDown())参考堆的布局和实现。
  1. #pragma once
  2. #include <vector>
  3. template<class T>
  4. class Less
  5. {
  6. public:
  7.         bool operator()(const T& x, const T& y)
  8.         {
  9.                 return x < y;
  10.         }
  11. };
  12. template<class T>
  13. class Greater
  14. {
  15. public:
  16.         bool operator()(const T& x, const T& y)
  17.         {
  18.                 return x > y;
  19.         }
  20. };
  21. namespace XiaoC
  22. {
  23.         //默认是大堆,排升序,用小于符号
  24.         template<class T, class Container = vector<T>, class Compare = Less<T>>
  25.         class priority_queue
  26.         {
  27.         public:
  28.                 void AdjustUp(int child)
  29.                 {
  30.                         Compare com;
  31.                         int parent = (child - 1) / 2;
  32.                         while (child > 0)
  33.                         {
  34.                                 //if (_con[parent] < _con[child])
  35.                                 if (com(_con[parent], _con[child]))
  36.                                 {
  37.                                         swap(_con[child], _con[parent]);
  38.                                         child = parent;
  39.                                         parent = (child - 1) / 2;
  40.                                 }
  41.                                 else
  42.                                 {
  43.                                         break;
  44.                                 }
  45.                         }
  46.                 }
  47.                 void push(const T& x)
  48.                 {
  49.                         _con.push_back(x);
  50.                         AdjustUp(_con.size() - 1);
  51.                 }
  52.                 void AdjustDown(int parent)
  53.                 {
  54.                         // 先假设左孩子小
  55.                         int child = parent * 2 + 1;
  56.                         Compare com;
  57.                         while (child < _con.size())  // child >= n说明孩子不存在,调整到叶子了
  58.                         {
  59.                                 // 找出小的那个孩子
  60.                                 //if (child + 1 < _con.size() && _con[child] < _con[child + 1])
  61.                                 if (child + 1 < _con.size() && com(_con[child], _con[child + 1]))
  62.                                 {
  63.                                         ++child;
  64.                                 }
  65.                                 //if (_con[parent] < _con[child])
  66.                                 if (com(_con[parent], _con[child]))
  67.                                 {
  68.                                         swap(_con[child], _con[parent]);
  69.                                         parent = child;
  70.                                         child = parent * 2 + 1;
  71.                                 }
  72.                                 else
  73.                                 {
  74.                                         break;
  75.                                 }
  76.                         }
  77.                 }
  78.                 void pop()
  79.                 {
  80.                         swap(_con[0], _con[_con.size() - 1]);
  81.                         _con.pop_back();
  82.                         AdjustDown(0);
  83.                 }
  84.                 const T& top() const
  85.                 {
  86.                         return _con[0];
  87.                 }
  88.                 size_t size() const
  89.                 {
  90.                         return _con.size();
  91.                 }
  92.                 bool empty() const
  93.                 {
  94.                         return _con.empty();
  95.                 }
  96.         private:
  97.                 Container _con;
  98.         };
  99. }
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
继续阅读请点击广告
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

汕尾海湾

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表