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

目录

一.容器适配器

1.2deque的原理介绍

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

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

stack的模拟实现

queue的模拟实现

二.优先级队列

2.1priority_queue的使用

三、总结

一.容器适配器

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的模拟实现

cpp 复制代码
#include<deque>
namespace zda
{
	template<class T, class Con = deque<T>>
	//template<class T, class Con = vector<T>>
	//template<class T, class Con = list<T>>
	class stack
	{
	public:
		stack() {}
		void push(const T& x) { _c.push_back(x); }
		void pop() { _c.pop_back(); }
		T& top() { return _c.back(); }
		const T& top()const { return _c.back(); }
		size_t size()const { return _c.size(); }
		bool empty()const { return _c.empty(); }
	private:
		Con _c;
	};
}

queue的模拟实现

cpp 复制代码
#include<deque>
#include <list>
namespace bite
{
	template<class T, class Con = deque<T>>
	//template<class T, class Con = list<T>>
	class queue
	{
	public:
		queue() {}
		void push(const T& x) { _c.push_back(x); }
		void pop() { _c.pop_front(); }
		T& back() { return _c.back(); }
		const T& back()const { return _c.back(); }
		T& front() { return _c.front(); }
		const T& front()const { return _c.front(); }
		size_t size()const { return _c.size(); }
		bool empty()const { return _c.empty(); }
	private:
		Con _c;
	};
}

二.优先级队列

2.1priority_queue的使用

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

cpp 复制代码
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
 
int main() {
    // 创建一个存储int类型元素的优先级队列
    priority_queue<int> pq;
 
    // 向队列中添加元素
    pq.push(1);
    pq.push(3);
    pq.push(2);
    pq.push(5);
    pq.push(1);
 
    // 输出队列中的元素,并观察优先级
    while (!pq.empty()) {
        cout << pq.top() << " ";
        pq.pop();
    }
    cout << endl;
 
    return 0;
}

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

cpp 复制代码
#include<iostream>
#include <vector>
#include <queue>
#include <functional>   
using namespace std;

void TestPriorityQueue()
{
	// 默认情况下,创建的是大堆,其底层按照小于号比较
	vector<int> v{ 3,2,7,6,0,4,1,9,8,5 };
	priority_queue<int> q1;
	for (auto& e : v)
		q1.push(e);
	cout << q1.top() << endl;

	// 如果要创建小堆,将第三个模板参数换成greater比较方式
	priority_queue<int, vector<int>, greater<int>> q2(v.begin(), v.end());
	cout << q2.top() << endl;
}
int main()
{

	TestPriorityQueue();

	// greater算法的头文件
	
}

三、总结

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

相关推荐
永不停转1 分钟前
C++宏定义中可变参数列表__VA_ARGS__ 及 QT 提供的宏 QT_OVERLOADED_MACRO
c++·qt
树下水月7 分钟前
关于使用python 安装 flask-openapi3扩展,使用docker 环境的完整复盘
开发语言·python·flask
时雨h7 分钟前
《Spring Boot+策略模式:企业级度假订单Excel导入系统的架构演进与技术实现》
开发语言·bash
丶Darling.11 分钟前
深度学习与神经网络 | 邱锡鹏 | 第二章学习笔记
深度学习·神经网络·学习
程序员JerrySUN19 分钟前
驱动开发硬核特训 · Day 1
java·linux·运维·开发语言·c++·驱动开发
明明明h20 分钟前
C#网络编程(Socket编程)
开发语言·网络·c#
clock的时钟25 分钟前
数据结构(一)KMP+滑动窗口+链表+栈+队列
数据结构·算法·链表
sugar__salt26 分钟前
各种排序思路及实现
数据结构·算法·排序算法
爱写代码的小朋友28 分钟前
PHP+Vue 3实现增删改查(CRUD)
开发语言·vue.js·php
Vitalia32 分钟前
⭐算法OJ⭐数据流的中位数【最小堆】Find Median from Data Stream
数据结构·c++·算法·最小堆