一、栈的介绍
栈(stack)是限定仅在表尾进行插入或删除操作的线性表表。因此,对栈来说表尾端有特殊的意义,称为栈顶(top),相应地,表头称为栈底(bottom)。不含元素的栈为空栈。
假设栈S = (a1,a2,a3,…an),则称a1为栈底元素,an为栈顶元素。栈中的元素按照a1,a2,a3,…an的次序入栈,退栈的第一个元素为栈顶元素。换句话说,栈的修改时按照后进先出的原则进行的即:LIFO。
要想在c++中使用容器栈,需要加上以下的头文件:
#include<iostream>
#include<stack>
using namespace std;
下面是stack的一些成员函数
Member functions
(constructor)
Construct stack (public member function )
empty
Test whether container is empty (public member function )
测试栈是否为空
size
Return size (public member function )
返回栈的大小
top
Access next element (public member function )
获取下一个元素(栈顶的元素)
push
Insert element (public member function )
插入元素
emplace
Construct and insert element (public member function )
构建和插入元素
pop
Remove top element (public member function )
移除栈顶元素
swap
Swap contents (public member function )
交换内容
举例如下:
emplace的例子:
// stack::emplace
#include <iostream> // std::cin, std::cout
#include <stack> // std::stack
#include <string> // std::string, std::getline(string)
int main ()
{
std::stack<std::string> mystack;
mystack.emplace ("First sentence");
mystack.emplace ("Second sentence");
std::cout << "mystack contains:\n";
while (!mystack.empty())
{
std::cout << mystack.top() << '\n';
mystack.pop();
}
return 0;
}
output:
mystack contains:
Second sentence
First sentence
swap的例子:
// stack::swap
#include <iostream> // std::cout
#include <stack> // std::stack
int main ()
{
std::stack<int> foo,bar;
foo.push (10); foo.push(20); foo.push(30);
bar.push (111); bar.push(222);
foo.swap(bar);
std::cout << "size of foo: " << foo.size() << '\n';
std::cout << "size of bar: " << bar.size() << '\n';
return 0;
}
output:
size of foo: 2
size of bar: 3
二、栈的一些经典例子
1.数制转换
十进制数N与其他的d进制数的转换,其中一个简单的算法基于以下原理:
N = (N div d)*d + N mod d.
代码展示:
#include <iostream>
#include<stack>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<string>
using namespace std;
stack<int> s;
int main()
{
int n;int d;
cin>>n>>d;
while(n!=0){
int res = n%d;
s.push(res);
n = n/d;
}
while(!s.empty()){
cout<<s.top();
s.pop();
}
cout<<endl;
return 0;
}
2.括号匹配
假设表达式中允许包含三种括号:圆括号和方括号大括号,其嵌套的顺序随意。检查括号是否匹配的方法可用“期待的急迫程度”这个概念来描述。例如考虑下列括号序列:
[([][])]
当计算机接收了第一个括号后,它就期待与其匹配的第八个括号的出现,然而等来的确是第二个括号,此时第一个括号职能暂时靠边,而迫切等待与第二个括号相匹配的的,第七个括号“)”的出现,类似的,因而等来了第三个括号”[“,其期待的急迫程度较第二个括号更加紧迫,则第二个括号要靠边站,依次类推。在算法中,每次读入一个括号:
是右括号,则置于栈顶。
是左括号,要么使栈顶的期待得以解除,要么不合法。
代码展示:
#include <iostream>
#include<stack>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<string>
using namespace std;
stack<char> res;
int main()
{
//cout<<res.top()<<endl;
//{[{(([[]]))}]}
//{([[[]]))}
string s;
cin>>s;
res.push((char)s[0]);
for(int i=1;i<s.size();i++){
if((res.top()== '{'&&(char)s[i] == '}')||(res.top()== '('&&(char)s[i] == ')')||(res.top()== '['&&(char)s[i] == ']')){
res.pop();
}else{
res.push(s[i]);
}
}
if(res.empty()){
cout<<"匹配成功"<<endl;
}else{
while(!res.empty()){
cout<<res.top();
res.pop();
}
cout<<endl;
cout<<"失败"<<endl;
}
return 0;
}
3表达式求值
形如:4+2*(3+5)+6/3 - 3/(1 + 2)
首先我们要规定+,-,*,/,(,)的优先级然后再进行计算。将操作数与操作符分隔开。分别存入一个栈中。
代码展示
#include <iostream>
#include<queue>
#include<algorithm>
#include<stack>
#include<cstring>
#include<string>
#include<stdio.h>
#include<vector>
using namespace std;
stack<int>opd;//操作数
stack<char>opc;//运算符
int priority[100];
char compare(char a,char b){
if(priority[a]==priority[b]||priority[a]<priority[b])
return '<';
if(priority[a]>priority[b])
return '>';
if(priority[a]==3&&priority[b]==0)
return '=';
if(priority[a]==-1&&priority['b']==-1)return '=';
}
int calculate(int a,int b,char o){
if(o=='+')return a+b;
if(o=='-')return a-b;
if(o=='*')return a*b;
if(o=='/')return a/b;
}
int main()
{
//算符优先级
opc.push('#');
priority['+'] = priority['-'] = 1;
priority['*'] = priority['/'] = 2;
priority['('] = 3;
priority[')'] = 0;
priority['#'] = -1;
string s;
cin>>s;
int a,b;
char o;
for(int i=0;i<s.size();i++){
char c = (char)s[i];
if(c<48||c>57){//十以内的数
switch(compare(c,opc.top())){
case '<':{
o = opc.top();
if(o!='('){
opc.pop();
b = opd.top();
opd.pop();
a = opd.top();
opd.pop();
int res = calculate(a,b,o);
//cout<<res<<","<<o<<a<<b<<endl;
opd.push(res);
}
if(c==')'){
opc.pop();
}else{
opc.push(c);
}
break;
}
case '>':{opc.push(c);break;}
case '=':{opc.pop();break;}
}
}else{
opd.push(c-48);
}
}
while(!opc.empty()){
o=opc.top();
if(o=='#')opc.pop();
else{
opc.pop();
b = opd.top();
opd.pop();
a = opd.top();
opd.pop();
int res = calculate(a,b,o);
//cout<<res<<","<<o<<a<<b<<endl;
opd.push(res);
}
}
//3*(2+5)+6/(2+1)+3*(1+3)/4+4*(1+2)#
cout<<opd.top()<<endl;
return 0;
}