stack:栈
queue:队列
两者都是容器适配器
通过容器的push_back等功能来实现
容器适配器 都不支持迭代器遍历 因为他们通常都包含一些特殊性质
如果支持迭代器随便遍历 那他们无法很好的保持他的性质
#include
#include
#include
#include
#include
using namespace std;namespace szh
{template//容器的类型 这个Container我也不知道 传什么就用什么class stack{public:void push(const T& x){_con.push_back(x);}void pop(){_con.pop_back();}size_t size(){return _con.size();}bool empty(){return _con.empty();}T& top(){return _con.back();}private:Container _con;};void test_stack(){//stack> st;//利用模板传vector//stack> st;//利用模板传list 两者都可以实现stack> st;st.push(1);st.push(2);st.push(3);st.push(4);while (!st.empty()){cout << st.top() << " ";st.pop();}cout << endl;}
}
queue同理
#include
#include
#include
#include
using namespace std;namespace szh
{template//容器的类型 这个Container我也不知道 传什么就用什么class queue{public:void push(const T& x){_con.push_back(x);}void pop(){_con.pop_front();}size_t size(){return _con.size();}bool empty(){return _con.empty();}T& front(){return _con.front();}T& back(){return _con.back();}private:Container _con;};void test_queue(){//queue> q;//vector不行 库里面的vector不支持头删 时间复杂度太高//queue> q;queue> q;q.push(1);q.push(2);q.push(3);q.push(4);while (!q.empty()){cout << q.front() << " ";q.pop();}cout << endl;}
}
总结一下:stl中的stack和queue是通过容器适配转换出来的 不是原生实现的 为什么呢? ->
复用 自己写一个容器适配也是可以的 所以没有写死
库里面是用deque来适配的
deque(双端队列):是一种双开口的"连续"空间的数据结构,双开口的含义是:可以在头尾
两端进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要搬
移元素;与list比较,空间利用率比较高。
排序效率相比vector较慢 不完美
下面测试一下效率
void dvcompare()
{deque d;vector v;const int n = 100000;int* a1 = new int[n];int* a2 = new int[n];srand(time(0));for (size_t i = 0; i < n; ++i){int x = rand();d.push_back(x);v.push_back(x);}size_t begin1 = clock();sort(d.begin(), d.end());size_t end1 = clock();size_t begin2 = clock();sort(v.begin(), v.end());size_t end2 = clock();cout << end1 - begin1 << endl;cout << end2 - begin2 << endl;//差了四倍左右//deque慢//vector快//所以deque替代不了vector 效率低了
}
使用
void test_deque()
{deque d;d.push_back(-1);d.push_back(1);d.push_back(2);d.push_back(5);d.push_back(0);d.push_front(10);for (size_t i = 0; i < d.size(); ++i){cout << d[i] << " ";}cout << endl;
}
实际上deque的结构 如下图
设计4个指针 类似小数组的组合
如何管理多个小数组buffer呢?
通过中控映射的方式 中控管理的指针数组 每个指针指向一个小数组
如何实现opeartor[]的随机访问呢?
通过指针的移动来访问数据
需要计算访问的第i个数据在哪个buffer
当数据量大了以后 效率就变低了
优先级队列 底层就是堆 默认是大堆 但是缺省符号给了小于 小堆需要改变符号 变成大于
那么默认是大堆 如果想建小堆 那么需要一个一个换符号 很麻烦
这时模板的优势就来了 再增加一个模板参数 控制大于号还是小于号
//默认升序 怎么排降序 通过仿函数比较大小
void test_sort()
{vector v;v.push_back(5);v.push_back(1);v.push_back(2);v.push_back(4);//升序less //greater gt;//sort(v.begin(), v.end(), gt);sort(v.begin(), v.end(), greater());for (auto e : v){cout << e << " ";}cout << endl;
}
void test_priority_queue()
{//priority_queue pq;//默认大的优先级高 //默认是大堆priority_queue,greater> pq;//如果想变成小的优先级高 如何操作? 仿函数 #include pq.push(3);pq.push(1);pq.push(9);pq.push(4);pq.push(2);while (!pq.empty()){cout << pq.top() << " ";pq.pop();}cout << endl;
}
#include
#include
using namespace std;namespace szh
{//默认是大堆template,class Compare = less>//标准库默认是大堆 但是缺省给了小于class priority_queue//默认vector 底层是堆 logN 二叉树{public://从小到大就是符号变一下 其他都一样 有没有很好的方式取控制符号?templatestruct less{//仿函数 函数对象bool operator()(const T& x1, const T& x2){return x1 < x2;}};templatestruct greater{//仿函数 函数对象bool operator()(const T& x1, const T& x2){return x1 > x2;}};//向上调整void AdjustUp(int child){Compare com;int parent = (child - 1) / 2;while (child > 0)//child==0的时候就不用调了{//if (_con[child] > _con[parent])if (com(_con[parent], _con[child]))//换顺序 默认是小于{swap(_con[parent], _con[child]);child = parent;parent = (child - 1) / 2;}else{break;}}}//向下调整void AdjustDown(int root){Compare com;int parent = root;int child = parent * 2 + 1;while (child < _con.size()){//选出左右孩子中大的那一个//if (child + 1 < _con.size() && _con[child + 1] > _con[child])if (child + 1 < _con.size() && com(_con[child], _con[child + 1]))//换顺序 默认是小于号{++child;}//if (_con[child] > _con[parent])if (com(_con[parent], _con[child])){swap(_con[child], _con[parent]);parent = child;child = parent * 2 + 1;}else{break;}}}void push(const T& x){_con.push_back(x);AdjustUp(_con.size() - 1);//向上调整 二叉树处}void pop(){swap(_con[0], _con[_con.size() - 1]);_con.pop_back();AdjustDown(0);//向下调整}T& top(){return _con[0];}size_t size(){return _con.size();}bool empty(){return _con.empty();}private:Container _con;};void test_priority_queue(){//priority_queue pq;//大堆priority_queue,greater> pq;//大于反而是小堆pq.push(3);pq.push(1);pq.push(9);pq.push(4);pq.push(2);while (!pq.empty()){cout << pq.top() << " ";pq.pop();}cout << endl;}
}
容器:string/vector/list/deque(序列式容器)
适配器:stack/queue/priority_queue
迭代器:iterator/const_iterator/reverse_iterator/const_reverse_iterator
算法:sort/find/reverse
仿函数:less/greater
deque的缺点:
大量的频繁opeartor[]的效率低
迭代器的遍历相对复杂 效率也有一些影响
vector缺点:
头插头删的效率低 空间不够用了增容代价大
list缺点:
不支持随机访问
priority_queue 优先级队列 大的小的谁优先级高是看场景的
#include
面试问题:能否设计出一个数据结构 解决vector和list的缺点
deque中控映射指针数组不够了增容就可以
但对比vector 一起去堆相同的10w个数据排序 deque效率相比vector差了4-5倍
【C++】10.stack和queue 完