栈的应用------表达式的计算
1 //表达式计算 2 //表达式转后缀表达式(逆波兰式) 3 4 #include <cstdio> 5 #include <cstring> 6 #include <cctype> 7 #include <algorithm> 8 9 //char stack-----定义堆栈,用于转换表达式 10 char stack[25] ; //定义一个栈来储存各种符号 11 int top = -1 ; //栈为空时栈顶标记为-1 12 13 void push ( char item ) 14 { 15 stack[++ top] = item ; //栈顶元素进栈(维持栈的性质) 16 } 17 18 char pop () 19 { 20 return stack[top --] ; //栈顶元素出栈(维持栈的性质) 21 } 22 23 //returns precedence of operators-----运算符的优先级处理 24 int precedence ( char symbol ) 25 { 26 switch ( symbol ) 27 { 28 case '+' : 29 case '-' : 30 return 2 ; 31 break ; 32 case '*' : 33 case '/' : 34 return 3 ; 35 break ; 36 case '^' : 37 return 4 ; 38 break ; 39 case '(' : 40 case ')' : 41 case '#' : 42 return 1 ; 43 break ; 44 } 45 } 46 47 //check whether the symbol is operator?-----检测符号是否为运算符 48 int isOperator ( char symbol ) 49 { 50 51 switch ( symbol ) //各种符号标记为0,数字标记为1。 52 { 53 case '+' : 54 case '-' : 55 case '*' : 56 case '/' : 57 case '^' : 58 case '(' : 59 case ')' : 60 return 1 ; 61 break ; 62 default : 63 return 0 ; 64 } 65 } 66 67 //converts infix expression to postfix-----中缀转后缀 68 void convert ( char infix[] , char postfix[] ) 69 { 70 int i , symbol , j = 0 ; 71 stack[++ top] = '#' ; //#在栈底,表示这栈里没有东西 72 73 for ( i = 0 ; i < strlen(infix) ; i ++ ) //将整个式子全部扫一遍 74 { 75 symbol = infix[i] ; 76 if ( isOperator(symbol) == 0 ) 77 { 78 postfix[j] = symbol ; //数字直接进入后缀表达式 79 j ++ ; 80 } 81 else 82 { 83 if ( symbol == '(' ) //前括号直接入栈 84 { 85 push ( symbol ) ; 86 } 87 else 88 { 89 if ( symbol == ')' ) //发现后括号后开始出栈 90 { 91 while ( stack[top] != '(' ) //出栈直至前括号 92 { 93 postfix[j] = pop() ; 94 j ++ ; 95 } 96 pop(); //前括号前的第一个符号也要出栈 97 } 98 else//如果没有检测到,并且不是数字时 99 { 100 if ( precedence(symbol) > precedence(stack[top]) ) //如果符合计算优先级,就直接将运算符进栈 101 { 102 push(symbol) ; 103 } 104 else//如果不符合运算优先级,就出栈知道符合为止,再进栈 105 { 106 while ( precedence(symbol) <= precedence(stack[top] )) 107 { 108 postfix[j] = pop() ; 109 j ++ ; 110 } 111 push(symbol) ; 112 } 113 } 114 } 115 } 116 } 117 while ( stack[top] != '#' )//如果栈中没有括号了,就将剩余的运算符全部出栈 118 { 119 postfix[j] = pop() ; 120 j ++ ; 121 } 122 postfix[j] = '\0' ; //null terminate string.-----在字符串最后用一个“\0”来终止 123 } 124 125 //int stack-----定义堆栈,用来计算后缀表达式(逆波兰式) 126 int stack_int[25] ; //定义栈来直接储存数字 127 int top_int = -1 ; //栈顶空用-1表示 128 129 void push_int ( int item ) //进栈 130 { 131 stack_int[++ top_int] = item; 132 } 133 134 char pop_int () //出栈 135 { 136 return stack_int[top_int--]; 137 } 138 139 //evaluates postfix expression-----计算后缀表达式 140 int evaluate ( char *postfix ) 141 { 142 char ch ; 143 int i = 0 , operand1 , operand2 ; 144 145 while ( ( ch = postfix[i++] ) != '\0' ) 146 { 147 if ( isdigit(ch) ) 148 { 149 push_int(ch - '0') ; //Push the operand-----将字符转换成数字,再入栈 150 } 151 else //Operator,pop two operands-----取出两个数来计算 152 { 153 operand2 = pop_int() ; 154 operand1 = pop_int() ; 155 switch ( ch ) //直接计算 156 { 157 case '+' : 158 push_int(operand1 + operand2) ; 159 break ; 160 case '-' : 161 push_int(operand1 - operand2) ; 162 break ; 163 case '*' : 164 push_int(operand1 * operand2) ; 165 break ; 166 case '/' : 167 push_int(operand1 / operand2) ; 168 break ; 169 case '^' : 170 push_int(operand1 ^ operand2) ; 171 break ; 172 } 173 } 174 } 175 return stack_int[top_int] ; //最后栈中只剩下一个数,即为计算结果 176 } 177 178 int main() 179 { 180 char infix[25] = "(-1)" , postfix[25] ; 181 convert(infix , postfix) ; 182 183 printf ( "Infix expression is: %s\n" , infix ) ; 184 printf ( "Postfix expression is: %s\n" , postfix ) ; 185 printf ( "Evaluated expression is: %d\n" , evaluate(postfix) ) ; 186 187 return 0 ; 188 }
经过一番的简略分析,其实栈的应用十分方便,且易于理解。
程序运行如下:
这是一个简单的运行结果!!!
跟着这个结果来分析一下表达式:
1、普通表达式:
这是我们人类平时用来计算的算式。在普通表达式中,符号总是在运算对象之间,有括号来限制运算顺序。------如(样例中):(-1) 即 0-1。
2、后缀表达式(又称:逆波兰式):
在后缀表达式中,符号总在运算对象之后,因为严格遵循从左往右计算,所以没有括号,方便计算机读取然后直接计算。------如(样例中):1- 即 01- 。
3、前缀表达式(又称:波兰式):
在前缀表达式中,符号总在运算对象之前,同逆波兰式,也十分方便计算机读取以及计算。------如(由样例): -1 即 -01 。
注:前缀表达式和后缀表达式都是由波兰数学家扬·武卡谢维奇1920年引入的数学表达式方式,为了纪念他所以称这种表达式为波兰式!!!