[C.C++] C++优先级队列

1113 0
Honkers 2025-5-11 16:29:27 来自手机 | 显示全部楼层 |阅读模式

目录

一、priority_queue的介绍

二、priority_queue的使用

三、priority_queue的模拟实现


一、priority_queue的介绍

1、优先队列是一种容器适配器,根据严格的弱排序标准,它的第一个元素总是它所包含的元素中最大的。

2、此上下文类似于堆,在堆中可以随时插入元素,并且只能检索最大堆元素(优先队列中位于顶部的元素)。

3、优先队列被实现为容器适配器,容器适配器即将特定容器类封装作为其底层容器类,queue提供一组特定的成员函数来访问其元素。元素从特定容器的“尾部”弹出,其称为优先队列的顶部。

4、底层容器可以是任何标准容器类模板,也可以是其他特定设计的容器类。容器应该可以通过随机访问迭代器访问,并支持以下操作:
empty():检测容器是否为空

size():返回容器中有效元素个数

front():返回容器中第一个元素的引用

push_back():在容器尾部插入元素、

pop_back():删除容器尾部元素

5、标准容器类vector和deque满足这些需求。默认情况下,如果没有为特定的priority_queue类实例化指定容器类,则使用vector。

6、需要支持随机访问迭代器,以便始终在内部保持堆结构。容器适配器通过在需要时自动调用算法函数
make_heap、push_heap和pop_heap来自动完成此操作。

二、priority_queue的使用

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

函数声明接口说明
priority_queue()/priority_queue(first,
last)
构造一个空的优先级队列
empty( )检测优先级队列是否为空,是返回true,否则返回
false
top( )返回优先级队列中最大(最小元素),即堆顶元素
push(x)在优先级队列中插入元素x
pop()删除优先级队列中最大(最小)元素,即堆顶元素

优先级队列的基本使用方法(针对基本数据类型)

  1. #include <iostream>
  2. #include <queue>
  3. #include <vector>
  4. #include <functional> // greater算法的头文件
  5. using namespace std;
  6. void TestPriorityQueue()
  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. cout << q1.top() << endl;
  14. // 如果要创建小堆,将第三个模板参数换成greater比较方式
  15. priority_queue<int, vector<int>, greater<int>> q2(v.begin(), v.end());
  16. cout << q2.top() << endl;
  17. }
  18. int main()
  19. {
  20. TestPriorityQueue();
  21. return 0;
  22. }
复制代码

对于自定义的数据类型的使用方法如下

如果在priority_queue中放自定义类型的数据,用户需要在自定义类型中提供> 或者< 的重载。

  1. #include <iostream>
  2. #include <queue>
  3. #include <vector>
  4. #include <functional> // greater算法的头文件
  5. using namespace std;
  6. class Date
  7. {
  8. public:
  9. Date(int year = 1900, int month = 1, int day = 1)
  10. : _year(year)
  11. , _month(month)
  12. , _day(day)
  13. {}
  14. bool operator<(const Date& d)const
  15. {
  16. return (_year < d._year) ||
  17. (_year == d._year && _month < d._month) ||
  18. (_year == d._year && _month == d._month && _day < d._day);
  19. }
  20. bool operator>(const Date& d)const
  21. {
  22. return (_year > d._year) ||
  23. (_year == d._year && _month > d._month) ||
  24. (_year == d._year && _month == d._month && _day > d._day);
  25. }
  26. friend ostream& operator<<(ostream& _cout, const Date& d)
  27. {
  28. _cout << d._year << "-" << d._month << "-" << d._day;
  29. return _cout;
  30. }
  31. private:
  32. int _year;
  33. int _month;
  34. int _day;
  35. };
  36. void TestPriorityQueue()
  37. {
  38. // 大堆,需要用户在自定义类型中提供<的重载
  39. priority_queue<Date> q1;
  40. q1.push(Date(2018, 10, 29));
  41. q1.push(Date(2018, 10, 28));
  42. q1.push(Date(2018, 10, 30));
  43. cout << q1.top() << endl;
  44. // 如果要创建小堆,需要用户提供>的重载
  45. priority_queue<Date, vector<Date>, greater<Date>> q2;
  46. q2.push(Date(2018, 10, 29));
  47. q2.push(Date(2018, 10, 28));
  48. q2.push(Date(2018, 10, 30));
  49. cout << q2.top() << endl;
  50. }
  51. int main()
  52. {
  53. TestPriorityQueue();
  54. return 0;
  55. }
复制代码

三、priority_queue的模拟实现

  1. #include <iostream>
  2. #include <vector>
  3. using namespace std;
  4. namespace priority_queue
  5. {
  6. template <class T>
  7. struct Less
  8. {
  9. bool operator() (const T& left, const T& right)
  10. {
  11. return left < right;
  12. }
  13. };
  14. template <class T>
  15. struct Greater
  16. {
  17. bool operator() (const T& left, const T& right)
  18. {
  19. return left > right;
  20. }
  21. };
  22. template <class T, class Container = vector<T>, class Compare = less<T>>//默认建立大堆
  23. class priority_queue
  24. {
  25. private:
  26. Container _con;
  27. Compare _cmp;
  28. void adjust_down(size_t parent)
  29. {
  30. size_t child = parent * 2 + 1;
  31. while (child < size())
  32. {
  33. if (child + 1 < size() && _cmp(_con[child], _con[child + 1]))
  34. {
  35. child += 1;
  36. }
  37. if (_cmp(_con[parent], _con[child]))
  38. {
  39. swap(_con[child], _con[parent]);
  40. parent = child;
  41. child = parent * 2 + 1;
  42. }
  43. else
  44. {
  45. break;
  46. }
  47. }
  48. }
  49. void adjust_up(size_t child)
  50. {
  51. size_t parent = (child - 1) / 2;
  52. while (child > 0)
  53. {
  54. if (_cmp(_con[parent], _con[child]))
  55. {
  56. swap(_con[child], _con[parent]);
  57. child = parent;
  58. parent = (child - 1) / 2;
  59. }
  60. else
  61. {
  62. break;
  63. }
  64. }
  65. }
  66. public:
  67. priority_queue()
  68. {}
  69. template <class InputIterator>
  70. priority_queue(InputIterator first, InputIterator last)
  71. {
  72. while (first != last)
  73. {
  74. push(*first);
  75. first++;
  76. }
  77. }
  78. void push(const T& d)
  79. {
  80. _con.push_back(d);
  81. adjust_up(size() - 1);
  82. }
  83. bool empty() const
  84. {
  85. return size() == 0;
  86. }
  87. size_t size() const
  88. {
  89. return _con.size();
  90. }
  91. void pop()
  92. {
  93. swap(_con[0], _con[size() - 1]);
  94. _con.pop_back();
  95. adjust_down(0);
  96. }
  97. const T& top() const
  98. {
  99. return _con[0];
  100. }
  101. };
  102. class Date
  103. {
  104. public:
  105. Date(int year, int month, int day)
  106. :_year(year),
  107. _month(month),
  108. _day(day)
  109. {}
  110. void print()const
  111. {
  112. cout << _year << "-" << _month << "-" << _day << endl;
  113. }
  114. bool operator< (const Date& d)const
  115. {
  116. if (_year < d._year)
  117. {
  118. return true;
  119. }
  120. else if (_year == d._year && _month < d._month)
  121. {
  122. return true;
  123. }
  124. else if (_year == d._year && _month == d._month && _day < d._day)
  125. {
  126. return true;
  127. }
  128. else
  129. {
  130. return false;
  131. }
  132. }
  133. bool operator> (const Date& d)const
  134. {
  135. if (_year > d._year)
  136. {
  137. return true;
  138. }
  139. else if (_year == d._year && _month > d._month)
  140. {
  141. return true;
  142. }
  143. else if (_year == d._year && _month == d._month && _day > d._day)
  144. {
  145. return true;
  146. }
  147. else
  148. {
  149. return false;
  150. }
  151. }
  152. int _year;
  153. int _month;
  154. int _day;
  155. };
  156. void priority_queue_test()
  157. {
  158. //priority_queue<int, vector<int>, Less<int>> pq;
  159. //pq.push(3);
  160. //pq.push(2);
  161. //pq.push(5);
  162. //pq.push(6);
  163. //pq.push(7);
  164. //pq.push(9);
  165. //while (!pq.empty())
  166. //{
  167. // cout << pq.top() << endl;
  168. // pq.pop();
  169. //}
  170. priority_queue<Date, vector<Date>, Less<Date>> pq;
  171. pq.push(Date(2022, 6, 21));
  172. pq.push(Date(1949, 10, 1));
  173. pq.push(Date(1976, 5, 4));
  174. pq.push(Date(1999, 6, 21));
  175. pq.push(Date(2008, 1, 1));
  176. pq.push(Date(2018, 1, 1));
  177. while (!pq.empty())
  178. {
  179. cout << pq.top()._year << "-" << pq.top()._month << "-" << pq.top()._day << endl;
  180. //pq.top().print();
  181. pq.pop();
  182. }
  183. }
  184. };
  185. int main()
  186. {
  187. priority_queue::priority_queue_test();
  188. return 0;
  189. }
复制代码
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

中国红客联盟公众号

联系站长QQ:5520533

admin@chnhonker.com
Copyright © 2001-2026 Discuz Team. Powered by Discuz! X3.5 ( 粤ICP备13060014号 )|天天打卡 本站已运行