我们先模拟实现, 然后根据代码讲解如何使用.
目录
一.栈
因为c++编译器中已经给出了stack, 所以我们在实现时把其放到自己的命名空间中.
1.stack类中的相关成员
采用模板类的方式实现, 可以针对于各种不同的数据, 因为c++中已经给出了很多可以用来实现stack的容器, 我们这里选用deque(双端队列).(deque在后面会详细讲解)
功能介绍:
①.push入栈.
②.pop出栈.
③.top访问栈顶元素.
④.size计算栈中元素个数.
⑤.empty判断栈中是否为空.
为什么使用deque而不是vector实现栈?
1.首先我们要知道, 我们实现的栈只有两种操作, 一种是push, 一种是pop, 也就是出栈和入栈两种操作, 因此使用vector, list, deque 都可以, 但他们的性能上有区别, 所以我们在使用的时候, 需要根据实际情况来选择使用那种容器, 但这里为什么将deque作为stack的默认容器呢? 我们平时在c中实现的satck都是使用动态数组来完成的, 也就是vector那么为什么在这里就不使用了, 其实它是考虑了扩容的问题, 因为我们使用vector, 一但容器容量满了, 就需要扩容, 但vector扩容时十分耗费资源, 需要重新申请空间和拷贝元素, 而如果我们使用deque的话, 实现push和pop两个操作和vector相似, 并且扩容时相对比较方便, 因此在这里编译器选择使用deque来作为stack的默认容器.
2.栈不需要遍历, 因此刚好把deque的劣势规避了, 所以使用deque更加合适.
template<class T, class Con = deque<T>>
class stack{
public:
stack();
void push(const T& x) ;
void pop() ;
T& top() ;
const T& top()const ;
size_t size()const ;
bool empty()const ;
private:
Con _c;
};
2.stack成员函数的具体实现
a.构造函数不需要显示定义, 默认的构造函数会调用deque的构造函数对类的数据成员进行初始化.
b.push入栈
void push(const T& x) {
_c.push_back(x);
}
直接调用deque的push_back函数, 向双端队列尾部插入元素即可.
c.pop出栈
void pop() {
_c.pop_back();
}
同理, 调用deque的pop_back函数, 从双端队列尾部删除元素即可.
d.top访问栈顶元素
T& top() {
return _c.back();
}
返回双端队列的尾部元素.(const类型的top与普通top完全相同)
e.size有效元素个数
size_t size()const {
return _c.size();
}
依然是返回双端队列中的有效元素个数, 调用deque的size函数.
f.empty判空
bool empty()const {
return _c.empty();
}
调用deque的empty函数, 判断双端队列中元素是否为空.
3.stack的使用
测试:
①.创建栈.
②.向栈中插入元素.
③.打印栈顶元素.
④.打印栈中元素个数.
⑤.出栈.
⑥.打印栈顶元素.
⑦.打印栈中元素个数.
lz::stack<int> s1;
s1.push(1);
s1.push(2);
s1.push(3);
s1.push(4);
s1.push(5);
s1.push(6);
cout << s1.top() << endl;
if (!s1.empty()) {
cout << s1.size() << endl;
}
s1.pop();
s1.pop();
s1.pop();
cout << s1.top() << endl;
if (!s1.empty()) {
cout << s1.size() << endl;
}
运行结果:
二.队列
同样我们的队列需要在自己的命名空间中实现.
1.queue类中的相关成员
采用模板类的方式实现, 应对于不同类型的数据, 底层使用的默认容器为deque.
功能介绍:
①.push入队列.
②.pop出队列.
③.back访问队列尾部元素.
④.front访问队列首部元素.
⑤.size返回队列中有效元素个数.
⑥.empty判断队列是否为空.
为什么默认容器使用deque而不使用list?
1.queue不需要存储一些额外的内容, 而list中的每个结点还存储了next | prev两个结构体指针, 所以使用list会浪费内存空间.
2.deque是分段连续的, 因此其缓存效率高.
3.queue不需要遍历, 因此规避了deque的劣势.
template<class T, class Con = deque<T>>
class queue{
public:
queue() ;
void push(const T&a