栈(stack)是一种实现后进先出(last-in, first out; LIFO)的容器。它是一种线性结构,当和向量、链表等线性数据结构不同的是,栈仅允许在一端进行操作:插入和删除。允许操作的一端成为栈顶(top),另一端就是栈低(bottom)。
栈(stack)是一种很重要的数据结构,用途也很广泛,如:表达式计算,函数调用的现场保护,递归调用所需要的递归工作栈等等都是基于栈这种数据结构。(除此之外还有很多应用)。
栈(stack)在C++标准模板库(STL)中实现了,以下是栈(stack)容器中的一些操作:
1 template <class T> 2 class stack 3 { 4 public: 5 stack(); 6 stack(const stack&); 7 ~stack(); 8 stack& operator =(const stack&); 9 int size() const; 10 bool empty() const; 11 int &top(); 12 void push(const int&); 13 void pop(); 14 //.. 15 };
在上面模板中可以看到,栈的主要操作有进栈(push),出栈(pop),取栈顶元素(top)和判断栈是否为空(empty)。
关于在如何使用STL中的栈结构,请参考www.cplusplus.com,那里有标准库所有容器的用法。
以下讨论两个栈的应用:
RPN计算器(RPN calculator)
RNP计算器是一种处理后缀表达式的计算器,其工作原理是,
1)输入的符号是一个数就压入栈(stack),
2)输入的是运算符就将栈顶的两元素弹出来进行计算,并把计算计算结果压入栈;
3)重复1),2)步骤,直到退出。
例如,3*(4+5)的后缀表示法是3 4 5 + *,按后缀表示法的顺序输入,就会得到27. 具体的实现
进制转换
日常我们都使用十进制来计算,但是在计算机中,十进制在很多时候是行不通的,必须进行进制转换,这也是学习程序设计的必修内容。
进制转换算法:
1、输入十进制整数N,基数B;
2、用B除N,将余数N%B压入栈,然后用商N/B代替N;
3、N/B为0结束,不为0就转到2。
此外还有:中缀表达式转后缀表达式,括号配对问题,调度问题也可以利用栈结构来解决。在ChinaUNIX的一个博客GP-King中有详细叙述。想了解可以去看看。
以下附上两个应用代码:
1 //RPN计算器 2 #include<iostream> 3 #include<stack> 4 #include<string> 5 #include<sstream> 6 using namespace std; 7 8 int main() 9 { 10 stack<char> oprtr; 11 stack<double> oprnd; 12 string input; 13 bool quit = false; 14 double x,y; 15 while(!quit) 16 { 17 cout<<"RPN> "; 18 cin>>input; 19 switch(input[0]) 20 { 21 case 'Q': 22 case 'q': 23 quit = true; 24 break; 25 case '+': 26 y=oprnd.top(); 27 oprnd.pop(); 28 x=oprnd.top(); 29 oprnd.pop(); 30 cout<<"\t"<<x<<" + "<<y<<" = "<<x+y<<endl; 31 oprnd.push(x+y); 32 break; 33 case '-': 34 y=oprnd.top(); 35 oprnd.pop(); 36 x=oprnd.top(); 37 oprnd.pop(); 38 cout<<"\t"<<x<<" - "<<y<<" = "<<x-y<<endl; 39 oprnd.push(x-y); 40 break; 41 case '*': 42 y=oprnd.top(); 43 oprnd.pop(); 44 x=oprnd.top(); 45 oprnd.pop(); 46 cout<<"\t"<<x<<" * "<<y<<" = "<<x*y<<endl; 47 oprnd.push(x*y); 48 break; 49 case '/': 50 y=oprnd.top(); 51 oprnd.pop(); 52 x=oprnd.top(); 53 oprnd.pop(); 54 cout<<"\t"<<x<<" / "<<y<<" = "<<x/y<<endl; 55 oprnd.push(x/y); 56 break; 57 case 'c': 58 case 'C': 59 while(!oprnd.empty()) 60 oprnd.pop(); 61 cout<<"Clear...\n"; 62 break; 63 default: 64 istringstream in(input); 65 in>>x; 66 oprnd.push(x); 67 } 68 } 69 return 0; 70 }
1 #include<iostream> 2 #include<string> 3 #include<stack> 4 using namespace std; 5 6 string dec2base(int num, int base) 7 { 8 string digitChar = "0123456789ABCDEF",numStr = ""; 9 stack<char> stk; 10 do{ 11 stk.push(digitChar[num%base]); 12 num/=base; 13 }while(num!=0); 14 15 while(!stk.empty()) 16 { 17 numStr+=stk.top(); 18 stk.pop(); 19 } 20 return numStr; 21 } 22 23 int main() 24 { 25 int num,base; 26 cout<<"Enter a number: "; cin>>num; 27 cout<<"Enter a number as base: "; cin>>base; 28 string s = dec2base(num,base); 29 cout<<s<<endl; 30 return 0; 31 }