图解数据结构(2)——栈

转载自http://www.cppblog.com/guogangj/archive/2009/10/14/98565.html

前一篇讲解了最基本的东西,这篇就稍微前进一点点,讲一下栈,栈在英文中叫Stack,翻译成中文又叫“堆栈”,但决不能称为“堆”,这个要搞清楚,我们说的“栈”和“堆栈”指的都是Stack这种数据结构,但“堆”却是另外一个概念了,这里且不提。

栈最大特点是先进后出,如图:

可以看出,栈有几个最常见的方法,或者说必备的方法,Push,Pop和Top,即进栈,出栈和取最顶元素。从代码上看,栈如何实现呢?用数组好还是用单向链表好呢?其实都可以,我下面的例子是用数组实现的。

说了那么多,栈有什么用呢?下面就举一个最经典的例题——逆波兰表达式(RPN,Reversed Polish Notation)的求解。

什么是逆波兰表达式?我们表述一个算式通常是这样:X+Y,即:“操作数1 操作符 操作数2”,当然也有比较特别的,比如“sqrt(N)”,sqrt是操作符,N是操作数,而逆波兰表达式则很统一,先操作数,后操作符,为什么叫“逆波兰表达式”?因为有一个波兰人发明了波兰表达式,而逆的波兰表达式就叫“逆波兰表达式”了。看下图就能很好理解了:

所有的算式都可以用逆波兰表达式写出来,只是我这里的举例是为了方便起见,限制在整数的四则运算里。

那假如现在我们有一个逆波兰表达式,那我们如何求出它的值呢?这里我们的“栈”就要派上用场了,由于操作数在操作符前面,所以我们按顺序遍历这个表达式,遇到操作数的时候进栈,遇到操作符时候让操作数出栈并运算,然后把运算结果进栈。过程如下图所示:

遇到第一个操作符,“+”的时候,由于需要两个操作数,所以出栈两次,4和3出栈,执行加法运算,结果是7,7进栈……依此类推。

下面我给出参考代码,我的代码使用很简单,复制,粘贴到一个cpp文件中,编译此cpp文件即可,没别的依赖。

  1. #include "stdio.h"  
  2. struct Cell  
  3. {  
  4.     int iType; // 0 - number, 1 - '+', 2 - '-', 3 - '*', 4 - '/'  
  5.     int iData;  
  6. };  
  7.   
  8. class Stack  
  9. {  
  10. public:  
  11.     Stack(int iAmount = 10);  
  12.     ~Stack();  
  13.   
  14.     //return 1 means succeeded, 0 means failed.  
  15.     int Pop(int& iVal);  
  16.     int Push(int iVal);  
  17.     int Top(int& iVal);  
  18. private:  
  19.     int *m_pData;  
  20.     int m_iCount;  
  21.     int m_iAmount;  
  22. };  
  23.   
  24. Stack::Stack(int iAmount)  
  25. {  
  26.     m_pData = new int[iAmount];  
  27.     m_iCount = 0;  
  28.     m_iAmount = iAmount;  
  29. }  
  30.   
  31. Stack::~Stack()  
  32. {  
  33.     delete m_pData;  
  34. }  
  35.   
  36. int Stack::Pop(int& iVal)  
  37. {  
  38.     if(m_iCount>0)  
  39.     {  
  40.         --m_iCount;  
  41.         iVal = m_pData[m_iCount];  
  42.         return 1;  
  43.     }  
  44.     return 0;  
  45. }  
  46.   
  47. int Stack::Push(int iVal)  
  48. {  
  49.     if(m_iCount<m_iAmount)  
  50.     {  
  51.         m_pData[m_iCount] = iVal;  
  52.         ++m_iCount;  
  53.         return 1;  
  54.     }  
  55.     return 0;  
  56. }  
  57.   
  58. int Stack::Top(int& iVal)  
  59. {  
  60.     if(m_iCount>0 && m_iCount<=m_iAmount)  
  61.     {  
  62.         iVal = m_pData[m_iCount-1];  
  63.         return 1;  
  64.     }  
  65.     return 0;  
  66. }  
  67.   
  68. int main(int argc, char* argv[])  
  69. {  
  70.     //12 3 4 + * 6 - 8 2 / +  
  71.     Cell rpn[11] = {  
  72.         0, 12,  
  73.         0, 3,  
  74.         0, 4,  
  75.         1, 0,  
  76.         3, 0,  
  77.         0, 6,  
  78.         2, 0,  
  79.         0, 8,  
  80.         0, 2,  
  81.         4, 0,  
  82.         1, 0};  
  83.   
  84.     Stack st;  
  85.   
  86.     // I won't check the return value for this is just a demo.  
  87.     int i, iOpt1, iOpt2;  
  88.     for(i=0; i<sizeof(rpn)/sizeof(Cell); i++)  
  89.     {  
  90.         switch(rpn[i].iType)  
  91.         {  
  92.         case 0: // number  
  93.             st.Push(rpn[i].iData);  
  94.             break;  
  95.         case 1: // +  
  96.             st.Pop(iOpt2);  
  97.             st.Pop(iOpt1);  
  98.             st.Push(iOpt1 + iOpt2);  
  99.             break;  
  100.         case 2: // -  
  101.             st.Pop(iOpt2);  
  102.             st.Pop(iOpt1);  
  103.             st.Push(iOpt1 - iOpt2);  
  104.             break;  
  105.         case 3: // *  
  106.             st.Pop(iOpt2);  
  107.             st.Pop(iOpt1);  
  108.             st.Push(iOpt1 * iOpt2);  
  109.             break;  
  110.         case 4: // /  
  111.             st.Pop(iOpt2);  
  112.             st.Pop(iOpt1);  
  113.             st.Push(iOpt1 / iOpt2);  
  114.             break;  
  115.         }  
  116.     }  
  117.   
  118.     int iResult;  
  119.     st.Pop(iResult);  
  120.     printf("The result is %d\n", iResult);  
  121.     return 0;  
  122. }  

猜你喜欢

转载自blog.csdn.net/ytlcainiao/article/details/45915233