翻译priority_queue就是优先级队列,本质其实就是一个堆,不传仿函数的情况下,默认是个大堆。
template
> class priority_queue { public: void adjust_up(int child) { int parent = (child - 1) / 2; while (child > 0) { if (_con[parent] < _con[child]) { ::swap(_con[parent], _con[child]); child = parent; parent = (child - 1) / 2; } else { break; } } } void adjust_down(int parent) { int n = size(); int child = parent * 2 + 1; while (child < n) { if (child + 1 < n && _con[child] < _con[child + 1]) { child++; } if (_con[parent] < _con[child]) { ::swap(_con[parent], _con[child]); parent = child; child = parent * 2 + 1; } else { break; } } } void push(const T& x) { _con.push_back(x); adjust_up(size() - 1); } size_t size() { return _con.size(); } bool empty() { return _con.empty(); } void pop() { assert(!empty()); ::swap(_con[0], _con[size() - 1]); _con.pop_back(); adjust_down(0); } const T& top() { return _con.front(); } private: Container _con; }; 关于实现,会写堆的向上和向下调整算法就很容易,由于之前写过相关的文章,这里就不过多的介绍了,
《数据结构初阶》二叉树之堆的实现和堆排序_李逢溪的博客-CSDN博客
《数据结构初阶》堆排序总结与思考_李逢溪的博客-CSDN博客_堆排序实验总结
接下来,我们的主要问题围绕:priority_queue是一个堆,默认是一个大堆,如何实现一个通用的模板,我们传一个less
类型,就能够生成一个大堆,传一个greater 类型,就能够生成一个小堆。这里就需要我们学习仿函数,本质仿函数是一种设计模式,什么是设计模式?就是写代码的经验,前人总结出来的写代码的方式。
仿函数本质上就是一个重载了operator()的类,由该类创建的对象可以像函数一样使用(),因此也被称作函数对象。
以下就是一个仿函数的简单使用:
template
class Less { public: bool operator()(const T& a, const T& b) { return a < b; } }; int main() { Less ls; cout << ls(3, 4) << endl; return 0; } less创建的对象ls,可以像函数一样使用ls(3,4),这就是一种仿函数的使用。
那么回到priority,如何写一个能够实例化出大堆和小堆的通用模板,这需要增加一个模板类型,然后由该类型创建一个对象,然后可以使用该对象实现child和parent<和>的比较。
template
class Greater { public: bool operator()(const T& a, const T& b) { return a > b; } }; template class Less { public: bool operator()(const T& a, const T& b) { return a < b; } }; template , class Compare = Less > class priority_queue { public: void adjust_up(int child) { Compare cmp; int parent = (child - 1) / 2; while (child > 0) { //if (_con[parent] < _con[child]) if (cmp(_con[parent], _con[child])) { ::swap(_con[parent], _con[child]); child = parent; parent = (child - 1) / 2; } else { break; } } } void adjust_down(int parent) { Compare cmp; int n = size(); int child = parent * 2 + 1; while (child < n) { //if (child + 1 < n && _con[child] < _con[child + 1]) if (child + 1 < n && cmp(_con[child], _con[child + 1])) { child++; } //if (_con[parent] < _con[child]) if (cmp(_con[parent], _con[child])) { ::swap(_con[parent], _con[child]); parent = child; child = parent * 2 + 1; } else { break; } } } void push(const T& x) { _con.push_back(x); adjust_up(size() - 1); } size_t size() { return _con.size(); } bool empty() { return _con.empty(); } void pop() { assert(!empty()); ::swap(_con[0], _con[size() - 1]); _con.pop_back(); adjust_down(0); } const T& top() { return _con.front(); } private: Container _con; }; 调用部分: