0


C++初阶学习第十三弹——容器适配器和优先级队列的概念

一.容器适配器

stack是一种后进先出的特殊线性数据结构,因此只要具有push_back()和pop_back()操作的线性结构,都可以作为stack的底层容器,比如vector和list都可以;
queue是先进先出的特殊线性数据结构,只要具有 push_back和pop_front操作的线性结构,都可以作为queue的底层容器,比如list。

虽然stack和queue中也可以存放元素,但在STL中并没有将其划分在容器的行列,而是将其称为容器适配 器,这是因为stack和队列只是对其他容器的接口进行了包装,STL中stack和queue默认使用deque,比如:

1.2deque的原理介绍

deque(双端队列):是一种双开口的"连续"空间的数据结构,双开口的含义是:可以在头尾两端进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要搬移元素;与list比较,空间利用率比较高。

1.3deque与vector和list的比较,以及deque的缺陷

与vector比较,deque的优势是:头部插入和删除时,不需要搬移元素,效率特别高,而且在扩容时,也不需要搬移大量的元素,因此其效率是必vector高的。

与list比较,其底层是连续空间,空间利用率比较高,不需要存储额外字段。

但是,deque有一个致命缺陷:不适合遍历,因为在遍历时,deque的迭代器要频繁的去检测其是否移动到某段小空间的边界,导致效率低下,而序列式场景中,可能需要经常遍历,因此在实际中,需要线性结构时,大多数情况下优先考虑vector和list,deque的应用并不多,而目前能看到的一个应用就是,STL用其作 为stack和queue的底层数据结构。

1.4为什么选择deque作为stack和queue的底层默认容器?

1. stack和queue不需要遍历(因此stack和queue没有迭代器),只需要在固定的一端或者两端进行操作。

2. 在stack中元素增长时,deque比vector的效率高(扩容时不需要搬移大量数据);queue中的元素增长时,deque不仅效率高,而且内存使用率高。 结合了deque的优点,而完美的避开了其缺陷。

** stack的模拟实现**

  1. #include<deque>
  2. namespace zda
  3. {
  4. template<class T, class Con = deque<T>>
  5. //template<class T, class Con = vector<T>>
  6. //template<class T, class Con = list<T>>
  7. class stack
  8. {
  9. public:
  10. stack() {}
  11. void push(const T& x) { _c.push_back(x); }
  12. void pop() { _c.pop_back(); }
  13. T& top() { return _c.back(); }
  14. const T& top()const { return _c.back(); }
  15. size_t size()const { return _c.size(); }
  16. bool empty()const { return _c.empty(); }
  17. private:
  18. Con _c;
  19. };
  20. }

queue的模拟实现

  1. #include<deque>
  2. #include <list>
  3. namespace bite
  4. {
  5. template<class T, class Con = deque<T>>
  6. //template<class T, class Con = list<T>>
  7. class queue
  8. {
  9. public:
  10. queue() {}
  11. void push(const T& x) { _c.push_back(x); }
  12. void pop() { _c.pop_front(); }
  13. T& back() { return _c.back(); }
  14. const T& back()const { return _c.back(); }
  15. T& front() { return _c.front(); }
  16. const T& front()const { return _c.front(); }
  17. size_t size()const { return _c.size(); }
  18. bool empty()const { return _c.empty(); }
  19. private:
  20. Con _c;
  21. };
  22. }

二.优先级队列

2.1priority_queue的使用

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

  1. #include <iostream>
  2. #include <queue>
  3. #include <vector>
  4. using namespace std;
  5. int main() {
  6. // 创建一个存储int类型元素的优先级队列
  7. priority_queue<int> pq;
  8. // 向队列中添加元素
  9. pq.push(1);
  10. pq.push(3);
  11. pq.push(2);
  12. pq.push(5);
  13. pq.push(1);
  14. // 输出队列中的元素,并观察优先级
  15. while (!pq.empty()) {
  16. cout << pq.top() << " ";
  17. pq.pop();
  18. }
  19. cout << endl;
  20. return 0;
  21. }

默认情况下,priority_queue是大堆, 如果要创建小堆,将第三个模板参数换成greater比较方式

  1. #include<iostream>
  2. #include <vector>
  3. #include <queue>
  4. #include <functional>
  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. // greater算法的头文件
  22. }

三、总结

容器适配器大致的内容就讲到这里,请大佬们多多支持!

标签: 学习 c++ 开发语言

本文转载自: https://blog.csdn.net/2302_81257639/article/details/143978633
版权归原作者 破浪前行之路 所有, 如有侵权,请联系我们删除。

“C++初阶学习第十三弹——容器适配器和优先级队列的概念”的评论:

还没有评论