前言:在下萌新,接触数据结构一月,代码未能完善之处,请多包含。如果同是萌新阅读文章,请理智看待,因为我并不是大佬。但是文章注释很全(鼠标移到图片上点击查看代码,即可看到所有注释),可以看到整个算法的思想,这点或许会帮助到各位萌新朋友。
如果是大佬观摩的话,希望各位大佬走的时候,能留个声音,因为在下太笨,希望得到各位的指点。
中缀表达式转后缀表达式算法思想:
- (1)遇到操作数,直接加入后缀表达式。
- (2)遇到界限符,如遇到“(” 直接入栈,遇到 “)”则依次弹出栈内运算符并加入后缀表达式,直到弹出“(”为止。注意的是,“(”不加入后缀表达式。
- (3)遇到运算符,依次弹出栈中优先级高于或等于当前运算符的所有运算符,并加入后缀表达式,若碰到“(”或栈空则停止。之后再把当前运算符入栈。
后缀表达式计算算法思想
- (1)从左往右扫描下一个元素,直到处理完所有元素;
- (2)若扫描到操作数则将其入栈,并回到(1),否则执行(3);
- (3)若扫描到运算符则出栈两个栈顶元素,执行相应计算,并将结果压入栈顶,回到(1)。(需要注意的是,在后缀表达式的机算中,先出栈的是右操作数)
//用栈转换中缀表达式为后缀表达式,并完成计算 #define MaxSize 10 typedef struct { char data[MaxSize]; int top; }Sqstack; void InitStack(S); //初始化栈 void Push(S, x); //入栈 void Pop(S); //出栈 bool StackEmpty(S); //判空 //用栈转换中缀表达式为后缀表达式 void Stack_expression(char a[], char b[], int length)//a是要转换的中缀表达式,b是完成后的后缀表达式,length是中缀表达式的长度。 { Sqstack Symbol; //定义一个运算符栈 int n = 0; for (int i = 0; i < length; i++) //遍历中缀表达式a,会遇到3种情况,遇到操作数,界限符和运算符 { //遇到操作数,直接加入后缀表达式 if (a[i] >= 48 && a[i] <= 57) { b[n] = a[i]; n++; } //遇到运算符,优先级高的运算符出栈加入后缀表达式 if (a[i] == '+' || a[i] == '-' || a[i] == '*' || a[i] == '/') { if (StackEmpty(Symbol)) //如果运算符栈为空,直接入栈 Push(Symbol, a[i]); else //不为空,则与栈内运算符逐个比较 { int j = 0; for (j = Symbol.top; j > -1; j--) //从栈顶往下依次比较 { if (Priority(a[i], Symbol.data[j])) //如果当前运算符优先级高于栈顶元素,则将其压入栈中,成为新的栈顶元素。另外Priority()是判断运算符优先级的函数。 { Push(Symbol, a[i]); break; //这里的break是跳出for循环,不是跳出if } else //当前运算符优先级低于或等同于栈顶元素,则弹出栈顶元素,加入后缀表达式 { b[n] = Symbol.data[j]; n++; Pop(Symbol); //这里相当于从栈中删除栈顶元素,因为它已经加入后缀式了 } } if (j == -1) //遍历到栈底,所有比当前运算符优先级高的元素都出栈后,把当前运算符入栈 Push(Symbol, a[i]); } } //遇到界限符 if (a[i] == '(' || a[i] == '[' || a[i] == '{') //遇到左括号直接将其入栈 Push(Symbol, a[i]); if (a[i] == ')') //遇到右括号,将栈内元素依次吐出 { while (Symbol.top != '(') //直到遇到左括号前,依次弹出栈内运算符加入后缀式 { b[n] = Symbol.data[Symbol.top]; n++; Symbol.top--; } } if (a[i] == ']') { while (Symbol.data[Symbol.top] != '[') { b[n] = Symbol.data[Symbol.top]; n++; Symbol.top--; } } if (a[i] == '}') { while (Symbol.data[Symbol.top] != '{') { b[n] = Symbol.data[Symbol.top]; n++; Symbol.top--; } } } } //后缀表达式的计算 void Operation(char b[], int length) { Sqstack Figure; //定义一个操作数栈 for (int i = 0; i < length; i++) { //如果是操作数直接入栈 if (b[i] >= 48 && b[i] <= 57) Push(Figure, b[i]); //如果是运算符,则弹出操作数栈栈顶两个元素参与运算,先出栈的是右操作数 else { char x = Figure.data[Figure.top]; char y = Figure.data[Figure.top - 1]; Figure.top = Figure.top - 2; char s = Calculate(x, y, b[i]); //Calculate()是计算函数 Push(Figure, s); //将结果压入操作数栈 } } int final_result = atoi(Figure.data[Figure.top]);//最终结果即是栈底元素,atoi()是字符串转整型函数 } //这里有两个函数没有实现 //bool Priority(a[i], Symbol.data[j]) 比较运算符优先级函数 //char Calculate(x, y, b[i]) 计算操作数函数
最终结果即是操作数栈中最后一个元素。