这篇主要写C++的栈和队列的类。用适配器模式写,也叫配接器。意思为可以将已有的东西转换为自己想要的,就和现实中电源适配器一样。
1、Stack模拟实现
用stack库来写。
#pragma once
#include <iostream>
#include <stack>
#include <vector>
#include <list>
using namespace std;
namespace zyd
{
template<class T, class Container>
class stack
{
public:
void push(const T& x)
{
_con.push_back(x);
}
void pop()
{
_con.pop_back();
}
const T& top()
{
return _con.back();
}
bool size()
{
return _con.size()
}
bool empty()
{
return _con.empty();
}
private:
Container _con;
};
void test_stack()
{
stack<int, vector<int>> st;
st.push(1);
st.push(2);
st.push(3);
st.push(4);
while (!st.empty())
{
cout << st.top() << " ";
}
cout << endl;
}
}
这里用了两个模板参数,T和Container。模板参数也可以传缺省值
class Container = vector< T >
这样就可以写成stack< int > st;
2、Queue模拟实现
#pragma once
#include <iostream>
#include <stack>
#include <vector>
#include <list>
using namespace std;
namespace zyd
{
template<class T, class Container = list<T>>
class queue
{
public:
void push(const T& x)
{
_con.push_back(x);
}
void pop()
{
_con.pop_front();
}
const T& front()
{
return _con.front();
}
const T& back()
{
return _con.back();
}
bool size()
{
return _con.size()
}
bool empty()
{
return _con.empty();
}
private:
Container _con;
};
void test_queue()
{
queue<int> q;
q.push(1);
q.push(2);
q.push(3);
q.push(4);
while (!q.empty())
{
cout << q.front() << " ";
q.pop();
}
cout << endl;
}
}
Queue抄袭一下栈,pop,front,back函数改一下,Container改成list< T >,因为vector不适合头删。
3、Deque双端队列
在栈和队列中,用的默认容器是deque,它集合了vector和list的功能,但实际上很少用它。
顺序表的缺点是头部中部插入删除效率低下,且扩容有风险,但优点是可以随机访问
链表缺点是不能随机访问,但优点是任意位置高效插入删除
deque做了一个折中方案。空间满了之后不扩容,直接再开一个空间,然后再去开一个指针数组,叫做中控数组,数组中部的指针指向开的第一个空间的头,剩下的空间的指针依次往后;头插的话就会另开一个空间,然后用中控数组中位于中部的指向第一个空间的指针的前一个指针来指向新空间,而尾插则在中控数组中指向最后一个空间的指针的下一个指针去指向一个新空间,所以头删尾删的操作也就明了了。这样看貌似它不扩容,但deque也扩容,扩容的是中控数组,然后把原有的指针拷贝过去即可,代价小。
头插就像这样。
扩容代价低。
头插头删,尾插尾删效率高
支持随机访问
缺点:
中间插入删除难(一个空间少了或多了一个值,随机访问就得改变数值了)(随机访问和中间插入就是只能一高一低的状态)
没有vector和list极致,平庸,可被替代
所以在库中它是作为vector和list的默认底层容器。
结束。