什么是栈?
1.栈(stack)是一种数据结构,是一种只能在一端进行插入和删除操作的特殊线性表。它按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出来)。栈具有记忆作用,对栈的插入与删除操作中,不需要改变栈底指针。
栈是允许在同一端进行插入和删除操作的特殊线性表。允许进行插入和删除操作的一端称为栈顶(top),另一端为栈底(bottom);栈底固定,而栈顶浮动;栈中元素个数为零时称为空栈。插入一般称为进栈(PUSH),删除则称为退栈(POP)。栈也称为先进后出表。
2.C++中的栈是是一个容器类的改编。容器适配器是一个封装了序列容器的类模板,它在一般序列容器的基础上提供了一些不同的功能。之所以称作适配器类,是因为它可以通过适配容器现有的接口来提供不同的功能。
3.栈可以用来在函数调用的时候存储断点;做递归时要用到栈;编辑器中的 undo (撤销)机制就是用堆栈来记录连续的变化,撤销操作可以取消最后一个操作,这也是发生在堆栈顶部的操作;编译器使用堆栈来解析算术表达式,
使用和常用函数
使用需包含头文件
#include <stack>
因为c++中栈是容器类的改编,所以它没有自己的构造函数。
模板参数
stack 容器适配器的模板有两个参数。第一个参数是存储对象的类型,第二个参数是底层容器的类型。stack 的底层容器默认是 deque 容器,因此模板类型其实是 stack<typename T, typename Container=deque>。通过指定第二个模板类型参数,可以使用任意类型的底层容器,只要它们支持 back()、push_back()、pop_back()、empty()、size() 这些操作。下面展示了如何定义一个使用 list 的堆栈:
std::stack<std::string,std::list<std::string>> ss;
栈初始化
创建栈时,不能在初始化列表中用对象来初始化,但是可以用另一个容器来初始化,只要栈的底层容器类型和这个容器的类型相同。
std::stack<int> values {1,2,3,4,5};//错误×
std::list<int> values {1,2,3,4,5};
std::stack<int,std::list<int>> my_stack (values);//正确
stack 模板定义了拷贝构造函数,因而可以复制现有的 stack 容器.
std::stack<int,std::list<int>>copy_stack {my_stack};
常用函数
top():返回一个栈顶元素的引用,类型为 T&。如果栈为空,返回值未定义。
push(const T& obj):可以将对象副本压入栈顶。这是通过调用底层容器的 push_back() 函数完成的。
push(T&& obj):以移动对象的方式将对象压入栈顶。这是通过调用底层容器的有右值引用参数的 push_back() 函数完成的。
pop():弹出栈顶元素。
size():返回栈中元素的个数。
empty():在栈中没有元素的情况下返回 true。
emplace():用传入的参数调用构造函数,在栈顶生成对象。
swap(stack & other_stack):将当前栈中的元素和参数中的元素交换。参数所包含元素的类型必须和当前栈的相同。对于 stack 对象有一个特例化的全局函数 swap() 可以使用。
小技巧
栈因为没有clear()方法,清空栈时就需要一个一个弹出,比较麻烦。这里提供一个清空栈的快速方法。
传统方法:
void clearStack(stack<elemType> &s){
while (!s.empty()){
s.pop();
}
}
快速方法:
oid clearStack(stack<elemType> &s){
s = stack<elemType>();
//直接移动拷贝一个空栈,结束旧栈生命周期
}
void clearStack(stack<elemType> &s){
stack<elemType>().swap(s);
//swap相当于交换了s和一个空临时stack的内容,然后临时stack再结束生命周期,但由于操作的是堆空间,其实还是一个一个释放空间,但是swap比pop要快
}