• C++优先级队列


    目录

    一、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
    2. #include
    3. #include
    4. #include // 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
    2. #include
    3. #include
    4. #include // 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 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, greater> 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
    2. #include
    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, class Compare = less>//默认建立大堆
    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, Less> 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, Less> 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. }
  • 相关阅读:
    phpstorm+phpstudy+xdebug快速搭建php调试环境
    某山词霸翻译js逆向分析
    图形学中一些基本知识的总结与复习
    FANUC机器人_通过ROBOGUIDE从零开始做一个离线仿真项目(2)
    Openssl, Alert, Fatal, handshake failure 40
    JDBC 和 DDT2
    Golang日志新选择:slog
    【FPGA】时序逻辑电路——基于计数器实现一个以1秒频率闪烁的LED灯
    恭喜元宇宙产业委秘书长何超、执行秘书长武艳芳成为南京河西CBD发展大使
    判断序列是否为正确的出栈序列
  • 原文地址:https://blog.csdn.net/qq_54178958/article/details/126360877