文章知識點來至於大話數據結構里邊章節知識, 這篇主要介紹棧與隊列在計算機中存儲形式, 以及在某些算法領域中對棧和隊列的相關應用。章節最后介紹了著名的逆波蘭表達式, 以及通過算法來實現該表達式的運算過程。 在實現代碼的同時添加了流程圖。相關代碼源碼請查看文章最后。
棧與隊列
1 棧結構定義
2 棧的順序存儲
3 兩棧共享空間
思路:他們是在數組的兩端,向中間靠攏top1和top2是兩個棧的棧頂指針, 只要兩個指針不碰頭就可以
圖解
4 棧的鏈式存儲
5 棧的順序存儲和鏈式存儲區別
如果棧使用過程中元素變化不可預測, 有時候小, 有時候非常大, 那么推薦用棧的鏈式存儲。 如果一直棧的的元素變化在可控范圍內, 推薦使用棧的順序存儲。
6 后綴表達式
表達式:9 3 1 – 3 * + 10 2 / +
規則:從左到右遍歷表達式中的每個數字和符號, 遇到是數字就進棧, 遇到事符號就就將棧頂兩個數字取出進行計算, 運算結果進棧, 一直到最終獲得結果。
5 中綴表達式轉后綴表達式
中綴表達式“9+(3-1)*3+10/2”轉化為后綴表達式“9 3 1 3 – 3 * + 10 2 / +”
規則:從左到右遍歷表達式的每個數字和符號,若是數字就輸出,就成為后綴表達式的一部分;若是符號,則判斷與其棧頂符號的優先級,是右括號或者優先級低於棧頂元素則棧頂元素以此出棧並輸出,並將當前符號進棧,一直到最終輸出后綴表達式。
6 隊列
定義:只允許在一段進行插入操作,而在另一端進行刪除操作的線性表。隊列是一種先進先出的線性表,簡稱FIFO。允許插入的一段陳為隊尾,允許刪除的一段稱為對頭
循環隊列
定義:我們把隊列頭尾相接的順序存儲結構稱為循環隊列
7 隊列的鏈式存儲
隊列的鏈式存儲結構其實就是線性表的單鏈表,只不過它只能頭出尾進,我們把它簡稱為隊列。
8 接下來開始對以上知識點實踐運用,我們已計算器為例來說明算法對於堆棧的使用。目的是計算表達式9+(3-1)*3+10/2的運行結果
首先我們熟悉下后綴表達式9 3 1 3 – 3 * + 10 2 / +, 他是通過中綴表達式9+(3-1)*3+10/2的來的。 關於中綴表達式轉后綴表達式:
中綴表達式“9+(3-1)*3+10/2”轉化為后綴表達式“9 3 1 3 – 3 * + 10 2 / +”
規則:從左到右遍歷表達式的每個數字和符號,若是數字就輸出,就成為后綴表達式的一部分;若是符號,則判斷與其棧頂符號的優先級,是右括號或者優先級低於棧頂元素則棧頂元素以此出棧並輸出,並將當前符號進棧,一直到最終輸出后綴表達式。
關於后綴表達式計算:
表達式:9 3 1 – 3 * + 10 2 / +
規則:從左到右遍歷表達式中的每個數字和符號, 遇到是數字就進棧, 遇到事符號就就將棧頂兩個數字取出進行計算, 運算結果進棧, 一直到最終獲得結果。
9 中綴表達式轉后綴表達式流程圖:
后綴表達式計算結果流程圖:
10 中綴表達式轉后綴表達式實現代碼:

public static string GetSufficExpression(string expression) { var expressionArray = expression.Split(' '); var operateStack = new StackLinkList(); var sufficExpression = string.Empty; for (var i = 0; i < expressionArray.Length; i++) { var input = expressionArray[i]; if (string.IsNullOrEmpty(input)) { continue; } if (IsNumber(input)) { sufficExpression += string.Format("{0} ", input); continue; } else if (input == ")") { while (true) { var popValue = operateStack.Pop(); if (popValue == "(") { break; } sufficExpression += string.Format("{0} ", popValue); } } else if (IsOperationChar(input)) { while (true) { if (operateStack.IsEmpty()) { operateStack.Push(input); break; } var popValue = operateStack.Pop(); if (!IsOperationChar(popValue)) { operateStack.Push(popValue); operateStack.Push(input); break; } if (ComparePriority(input, popValue) <= 0) { sufficExpression += string.Format("{0} ", popValue); } else { operateStack.Push(popValue); operateStack.Push(input); break; } } } else { operateStack.Push(input); } } while (true) { if (operateStack.IsEmpty()) { break; } sufficExpression += string.Format("{0} ", operateStack.Pop()); } return sufficExpression; }
后綴表達式計算結果代碼:

public static string GetCalculateResult(string sufficExpression) { var operateStack = new StackLinkList(); var expressionArray = sufficExpression.Split(' '); for (int i = 0; i < expressionArray.Length; i++) { var inputChar = expressionArray[i]; if (string.IsNullOrEmpty(inputChar)) { continue; } if (!IsOperationChar(inputChar) && !IsNumber(inputChar)) { throw new ArgumentException(); } if (IsNumber(inputChar)) { operateStack.Push(inputChar); } else { int stackTopLeft; int stackTopRight; if (!int.TryParse(operateStack.Pop(), out stackTopRight) || !int.TryParse(operateStack.Pop(), out stackTopLeft)) { throw new InvalidOperationException(); } operateStack.Push(Caculator(inputChar, stackTopLeft, stackTopRight).ToString(CultureInfo.InvariantCulture)); } } return operateStack.Pop(); }
單元測試:

private static void TestCaculator() { var sufficExpression = Calculator.GetSufficExpression("9 + ( 3 - 1 ) * 3 + 10 / 2"); Assert.IsEqual(sufficExpression.Trim(' '), "9 3 1 - 3 * + 10 2 / +"); var caculateResult = Calculator.GetCalculateResult(sufficExpression); Assert.IsEqual(caculateResult, "20"); var sufficExpression1 = Calculator.GetSufficExpression("9 + ( 3 - 1 )"); Assert.IsEqual(sufficExpression1.Trim(' '), "9 3 1 - +"); var caculateResult1 = Calculator.GetCalculateResult(sufficExpression1); Assert.IsEqual(caculateResult1, "11"); var sufficExpression2 = Calculator.GetSufficExpression("9 + ( 3 - 1 ) * 2 + 8 / 2 * 3"); Assert.IsEqual(sufficExpression2.Trim(' '), "9 3 1 - 2 * + 8 2 / 3 * +"); var caculateResult2 = Calculator.GetCalculateResult(sufficExpression2); Assert.IsEqual(caculateResult2, "25"); }
最后附上源代碼下載地址: