1. 程式人生 > >棧應用二(表達式求值)

棧應用二(表達式求值)

表達式求值 分享 問題 3.2 依次 滿足 pre index 拼接

問題;設計一個程序,演示用算符優先法對算術表達式求值的過程。利用算符優先關系,實現對算術四則混合運算表達式的求值。
(1)輸入的形式:表達式,例如3+2*6-4
包含的運算符只能有‘+‘ 、‘-‘ 、‘*‘ 、‘/‘(目前還不兼容括號) ;
(2)輸出的形式:運算結果,例如3+2*6-4=11;

(3)程序所能達到的功能:對表達式求值並輸出;示例:①3+2*6-4 ②30+20*6-80 ③2*7-3*5-3

思路:1.程序掃描表達式,一個一個的掃描
2.當發現這個字符是數字的時候,直接入數棧(需要處理多位數字字符)
3.如果發現是運算符
3.1如果符號棧為空,就直接入符號棧
3.2如果符號棧不為空,就要判讀。如果當前運算符的優先級小於等於符號棧頂的這個運算符的優先級,就計算,並把計算結果入數棧,然後把當前符號入棧(兼容多個減號一起出現,計算先後順序的問題)
3.3如果符號棧不為空,就要判讀。如果當前運算符的優先級大於符號棧頂的這個運算符的優先級,就入棧
4.當掃描完畢後,就依次彈出數棧和符號棧的數據,並計算,最終留在數棧的值,就是運算結果。

代碼:

技術分享
  1 <?php
  2 //棧的應用 表達式求值:3+2*6-2
  3 class Stack
  4 {
  5     private $top=-1;//默認是-1, 表示該棧是空的
  6     private $max_size = 100;//棧的最大容量
  7     private $stack = array();
  8     
  9     /**
 10      * 入棧
 11      */
 12     public function push($val)
 13     {
 14         if($this->top == $this
->max_size-1)//棧滿 15 { 16 return false; 17 } 18 $this->top++; 19 $this->stack[$this->top] = $val; 20 } 21 22 /** 23 * 出棧 24 */ 25 public function pop() 26 { 27 if($this->top == -1)//棧空 28 {
29 return false; 30 } 31 $value = $this->stack[$this->top]; 32 $this->top--; 33 return $value; 34 } 35 36 /** 37 * 取棧頂元素 38 */ 39 public function get_top() 40 { 41 if($this->top == -1) 42 { 43 return false; 44 } 45 return $this->stack[$this->top];//返回棧頂的元素,只取,但是不出棧 46 } 47 48 /** 49 * 判斷是否為空棧 50 */ 51 public function is_empty() 52 { 53 if($this->top == -1) 54 { 55 return true; 56 } else { 57 return false; 58 } 59 } 60 61 /** 62 * 判斷是不是一個運算符 63 */ 64 public function is_oper($ch) 65 { 66 if($ch==‘+‘ || $ch==‘-‘ || $ch==‘*‘ || $ch==‘/‘) 67 { 68 return 1; 69 } else { 70 return 0; 71 } 72 } 73 74 /** 75 * 判斷運算符的優先級 76 * *和/為1 +和-為0 括號後面改進 77 */ 78 public function PRI($ch) 79 { 80 if($ch==‘*‘ || $ch==‘/‘) 81 { 82 return 1; 83 } else if($ch==‘+‘ || $ch==‘-‘){ 84 return 0; 85 } 86 } 87 88 /** 89 * 計算的函數 90 */ 91 public function get_result($num1, $num2, $oper) 92 { 93 $res = 0; 94 switch($oper){ 95 case ‘+‘: 96 $res = $num1 + $num2; 97 break; 98 case ‘-‘: 99 $res = $num2 - $num1;//註意順序 100 break; 101 case ‘*‘: 102 $res = $num1 * $num2; 103 break; 104 case ‘/‘: 105 $res = $num2 / $num1;//註意順序 106 break; 107 } 108 return $res; 109 } 110 } 111 112 /** 113 * 計算(參數校驗省略) 114 */ 115 function calculator($operStack, $numsStack, $exp) 116 { 117 $index = 0;//$index就是一個掃描標記 118 $len = strlen($exp); 119 $nums = ‘‘;//用於拼接多位數的字符串 120 while(true) 121 { 122 $ch = substr($exp, $index, 1);//從$exp裏的$index位置取出一個字符 123 $is_oper = $operStack->is_oper($ch); 124 if($is_oper)//判斷$ch是不是運算符 125 { 126 //說明是運算符 127 /** 128 * 1.如果符號棧為空,就直接入棧; 129 * 2.如果符號棧不為空,如果當前運算符的優先級小於等於符號棧頂運算符的優先級,就計算,並把計算結果入數棧, 130 * 然後把當前符號入符號棧; 131 * 3.如果符號棧不為空,如果當前運算符的優先級大於符號棧頂運算符的優先級,就入棧 132 */ 133 if($operStack->is_empty()) 134 { 135 $operStack->push($ch); 136 } else { 137 //判斷當前符號跟棧頂符號的運算符優先級 138 $chPRI = $operStack->PRI($ch); 139 //只要你準備入符號棧的運算優先級小於等於當前棧棧頂的運算優先級,就一直計算 140 //直到這個條件不滿足,才把當前的符號入符號棧 141 //並且只要符號棧不為空 142 while(!$operStack->is_empty() && $chPRI<=$operStack->PRI($operStack->get_top()))//處理2*7-3*5-3這種情況 143 { 144 //計算 145 //從數棧裏面依次出兩個數 146 $num1 = $numsStack->pop(); 147 $num2 = $numsStack->pop(); 148 149 //再從符號棧裏取出一個運算符 150 $oper = $operStack->pop(); 151 $res = $operStack->get_result($num1, $num2, $oper); 152 153 //$res入棧 當前操作符入棧 154 $numsStack->push($res); 155 } 156 $operStack->push($ch); 157 } 158 } else { 159 $nums .= $ch;//處理多位數字 160 //判斷數字是否是最後一個,是:直接入棧;否:接著判斷下一個字符是否是數字 161 if($index == $len-1) 162 { 163 $numsStack->push($nums); 164 } else { 165 //判斷下一個字符是否是數字 166 if($operStack->is_oper(substr($exp, $index+1, 1))) 167 { 168 $numsStack->push($nums); 169 $nums = ‘‘;//置空 170 } 171 } 172 } 173 $index++;//讓$index指向下一個字符 174 if($index == $len)//判斷是否掃碼完畢 175 { 176 break;//當掃描完畢後,就break 177 } 178 } 179 180 /** 181 * 4.當掃描完畢後,就依次彈出數棧和符號棧的數據,並計算,最終留在數棧的值,就是運算結果 182 */ 183 while(!$operStack->is_empty()) 184 { 185 $num1 = $numsStack->pop(); 186 $num2 = $numsStack->pop(); 187 $oper = $operStack->pop(); 188 $res = $operStack->get_result($num1, $num2, $oper); 189 $numsStack->push($res); 190 } 191 192 return $numsStack->get_top(); 193 } 194 195 $exp = "7*2-5*3-3"; 196 $exp = "30+20*6-80"; 197 $exp = "3+2*6-4"; 198 $numsStack = new Stack(); 199 $operStack = new Stack(); 200 $res = calculator($operStack, $numsStack, $exp); 201 202 var_dump($res);
View Code

棧應用二(表達式求值)