首页 > 其他分享 >STL-priority_queue模拟实现

STL-priority_queue模拟实现

时间:2024-02-27 22:46:42浏览次数:17  
标签:queue right parent STL priority child push left con


#include<deque> //测试用 #include<vector>//测试用 #include"9Date.h"//测试用 #include<iostream> using std::cout; using std::endl; using std::cin; namespace test { template <class T > struct less { bool operator()(const T& x, const T& y) { return x < y; } }; template<class T> struct greater { bool operator()(const T& x, const T& y) { return x > y; } }; template<class T, class Containers = std::vector<T>, class Compare = less<T> > class priority_queue { private: Containers _con; Compare _com;//或者换成匿名对象,感觉更爽 public: void adjust_up(int child) { /** * 向上调整算法(大堆) * 计算父亲下标 * 如果孩子大于父亲,交换孩子和父亲,计算新父亲下标 * 如果孩子小于父亲,结束循环 * 相等换不换都行 * * */ /** * 计算堆的parent方法: * 写一个有序值为下标的数组小堆,0-4五个数刚好,计算3和4通过什么方法得到1 * * 0 * 1 2 * 3 4 * * (4-1)/2 = 3/2 = 1 * 4/2 - 1 = 2-1 = 1 * (3-1)/2 = 2/2 = 1 * 3/2 - 1 = 1-1 = 0; * 所以parent = (child-1)/2 */ int parent = (child - 1) / 2; while (child > 0) //child为0就不用再换了 { if (_com(_con[parent] ,_con[child])) //if (Compare()(_con[parent] ,_con[child])) { swap(_con[parent], _con[child]); child = parent; parent = (child - 1) / 2; } else { break; } } } void push(const T& x) { _con.push_back(x); adjust_up(_con.size()-1); } void adjust_down(int parent) { /** * 向下调整算法(大堆): * 计算孩子下标 * 计算最大的孩子 * 比较孩子和父亲 * 如果父亲小于最大孩子,交换父亲和孩子,计算新孩子 * 如果父亲大于于最大孩子,结束循环 * 相等换不换都行 * * 循环条件:左孩子下标不能超过数组大小 * * */ /** * 计算堆的child方法 * 写一个有序值为下标的数组小堆,0-4五个数刚好,计算 * 0 * 1 2 * 3 4 * 0*2+1 = 0+1 = 1 left * 0*2+2 = 0+2 = 2 right * 1*2+1 = 2+1 = 3 left * 1*2+2 = 2+2 = 4 right * 所以 left child = parent*2 + 1; * 所以 right child = parent*2 + 2; * 实际 right_child = left_child+1 */ //方法一 /* int left_child = parent * 2 + 1; //int right_child = parent * 2 + 2; int right_child = left_chile + 1; int min_child = left_child; while (left_child < _con.size() ) //不能限制右孩子,在没有右孩子,但有左孩子更小的情况,parent需要和左孩子交换,如果右孩子限制了,那可能会丢失一个左孩子 { if (right_child < _con.size() && left_child > right_child) { min_child = right_child; } if (_con[parent] < _con[child]) { swap(_con[parent], _con[min_child]); left_child = parent * 2 + 1; //right_child = parent * 2 + 2; right_child = left_child + 1; min_child = left_child; } else { break; } } */ ///优化方案 size_t child = parent * 2 + 1; while (child < _con.size()) { //if ((child + 1 )< _con.size() && _con[child]<_con[child + 1] ) if ((child + 1 )< _con.size() && _com(_con[child],_con[child + 1]) ) { child = child + 1; } if (_com(_con[parent] , _con[child])) { swap(_con[parent], _con[child]); parent = child; child = parent * 2 + 1; } else { break; } } } void pop() { swap(_con[0], _con[_con.size() - 1]); _con.pop_back(); adjust_down(0); } const T& top() { return _con[0]; } bool empty() { return _con.empty(); } size_t size() { return _con.size(); } }; //测试用例 void test_priority_queue1() { priority_queue<int , std::deque<int>,greater<int>> pq; //priority_queue<int> pq; pq.push(2); pq.push(4); pq.push(1); pq.push(3); pq.push(6); pq.push(5); while (!pq.empty()) { cout << pq.top() << endl; pq.pop(); } } //struct DateLess //这个不需要重载,我们在上方写了模板,参数T可以支持了 //{ // bool operator()(const Date& x, const Date& y) // { // return x < y; // } //}; struct PDateLess { bool operator()(const Date* p1, const Date* p2) { return (*p1) < (*p2); } }; void test_priority_queue2() { //priority_queue<Date> pq1; //pq1.push(Date(2001, 1, 1)); //pq1.push(Date(2001, 1, 2)); //pq1.push(Date(2001, 1, 3)); //cout << pq1.top() << endl; cout << "=================" << endl; priority_queue<Date*,std::vector<Date*>,PDateLess> pq2; //显式指定才会调用PDateLess,不然会调用模板的用于比较地址 pq2.push(new Date(2001, 1, 1)); pq2.push(new Date(2001, 1, 2)); pq2.push(new Date(2001, 1, 3)); cout << *(pq2.top()) << endl; } }

 

标签:queue,right,parent,STL,priority,child,push,left,con
From: https://www.cnblogs.com/DSCL-ing/p/18038585

相关文章

  • STL-string模拟实现
    1#pragmaonce23#include<iostream>4#include<string.h>5#include<assert.h>6usingstd::cout;7usingstd::endl;8usingstd::cin;9namespacetest{1011classstring{12//friendstd::ostream&......
  • C++ STL 容器 forward_list类型
    C++STL容器forward_list类型介绍std::forward_list是C++标准模板库(STL)中的一个单向链表容器。与std::list不同,std::forward_list只允许从头部到尾部的单向迭代,不支持反向迭代。因此,std::forward_list在某些操作上可能比std::list更高效,尤其是在插入和删除元素时......
  • STL-vector模拟实现
    #pragmaonce#include<assert.h>#include<iostream>usingstd::cout;usingstd::endl;usingstd::cin;namespacetest{//#include<algorithm>//模板参数省略:1.作为时2.作为类型名template<classT>//数组名:类型名:xx数组classvector......
  • STL-list模拟实现
    #pragmaonce#include"16my_Itetator.h"//测试用#include<iostream>//测试用usingstd::cout;usingstd::endl;usingstd::cin;namespacetest{//struct默认权限是public,一般也不会加权限,class才会(需要封装时使用class)//结点使用struct的好处是开放结点,......
  • STL-stack模拟实现
    #pragmaonce#include<assert.h>#include<list>#include<vector>#include<deque>#include<iostream>usingstd::cout;usingstd::endl;usingstd::cin;namespacetest{//template<classT,classContainers=std::vector&......
  • STL-queue模拟实现
    #include<list>#include<assert.h>#include<deque>#include<iostream>usingstd::cout;usingstd::endl;usingstd::cin;namespacetest{//template<classT,classContainers=std::list<T>>template<classT,c......
  • C++ STL 容器 list类型
    C++STL容器list类型list对于异常支持很好,要么成功,要么不会发生什么事情以下是std::list在异常处理方面表现良好的几个原因:动态内存管理:std::list使用动态内存分配来存储元素,这意味着它会在需要时自动分配内存,并在不再需要时释放内存。这种自动管理可以减少内存泄漏和悬......
  • CF85B Embassy Queue
    好久没水题解了,来水一道。题目传送门:Luogu&&Codeforces题意有\(n\)个人在\(c_i\)个时刻来办事,共\(3\)个窗口,每个人到每个窗口办事分别需要不同的事件,每个窗口只能同时处理一个人,问在最优安排下,办事时间最长的人最少需要多少时间。(实际上翻译说得已经很清楚了)思路一眼......
  • C++ STL 容器-Deque
    C++STL容器-Dequestd::deque(双端队列)是C++标准模板库(STL)中的一个容器,它支持在序列的两端快速插入和删除元素。与std::vector和std::list等其他序列容器相比,std::deque在某些特定场景下具有独特的优势。元素的访问和迭代比vector慢,迭代器不是普通的指针。以下是std::deque的一......
  • C++ STL 容器-Vector类型
    C++STL容器-Vector类型std::vector是C++标准库中的一个动态数组容器,它提供了随机访问迭代器,因此你可以像使用普通数组一样使用vector。vector容器可以动态地增长和缩小,这意味着你可以在不预先指定数组大小的情况下向其中添加或删除元素。特点动态大小:vector的大小可以在运......