中缀表达式转为后缀表达式的堆栈实现
中缀表达式
日常用到的表达式。
1+2*3-4
1+2-3*4/5
后缀表达式
把运算符放在两运算数后。每次遇到运算符时就将前两个运算数进行运算。
1 2 3 * + 4 -
1 2 + 3 4 * 5 / -
.
.
.
.
一个人学习cpp太艰难了
希望有大佬指点或者相互讨论学习
/*
Name: 中缀表达式转为后缀表达式的堆栈实现
Copyright:
Author: 小张同学.AC
Date: 28/09/21 20:01
Description:
完成了只含四则运算的表达式,还没考虑有括号的情况。
用到了引用,得在.cpp中运行 。
堆栈由链表实现。
我用的编译器是DveC++ 5.4.0。
*/
#include <stdio.h>
#include <stdlib.h>
typedef char ElementType;
typedef struct SNode{
ElementType Data;
struct SNode *Next;
}Stack;
char Number[] = {'0','1','2','3','4','5','6','7','8','9',};
char Space = ' ';
/* 以下用链表实现堆栈的相关函数 */
int IsEmpty(Stack* S){//判断堆栈是否空
return (S->Next == NULL);
}
Stack* CreateStack(){
Stack* S;
S = (Stack*)malloc(sizeof(Stack));
S->Next = NULL;
return S;
}
void Push(Stack* S, ElementType item){
Stack* tmpCell;//以malloc函数申请空间,不需要对堆栈满进行判断
tmpCell = (Stack*)malloc(sizeof(Stack));
tmpCell->Data = item;
tmpCell->Next = S->Next;
S->Next = tmpCell;
}
ElementType Pop(Stack* S){
Stack* FirstCell;
ElementType TopElem;
if(IsEmpty(S)){
printf("堆栈空!");
return NULL;
}else{
FirstCell = S->Next;
S->Next = FirstCell->Next;
TopElem = FirstCell->Data;
free(FirstCell);
return TopElem;
}
}
/* 链表实现堆栈结束 */
//读入中缀表达式
int Scan(ElementType &item){
int Flag = 0;
scanf("%c", &item);
return item == '\n' ? 0 : 1;//若读到回车说明输入结束
}
void Print(ElementType &item){
printf("%c", item);
}
int IsNumber(ElementType &item){
int Flag = 0;
int i;
for(i=0; i<sizeof(Number)/sizeof(char); i++){//循环判断是不是数字
if(item == Number[i]){
Flag = 1;
break;
}
}
return Flag;
}
/* 转为后缀表达式关键函数 (⊙o⊙)…就是处理优先级的问题 */
void PK(Stack* S, ElementType thisItem){
ElementType preItem;
if(IsEmpty(S)){//如果是堆栈是空,则直接进栈
Push(S, thisItem);
}else{
while(!IsEmpty(S)){
/* 弹出前一个运算符 */
preItem = Pop(S);
/* 在这里对前一个运算符和当前运算符做一些优先级处理
对“+”“-”用1标志;对“*”“/”用2标志 */
int flagPre, flagThis;
flagThis = (thisItem == '+' || thisItem == '-') ? 1 : 2;
flagPre = (preItem == '*' || preItem == '/') ? 2 : 1;
/* 循环弹出堆栈内的运算符进行比较 */
if(flagPre >= flagThis){
/* 若前一个运算符优先级高于当前运算符优先级 或者 级别相同,则弹出前一个运算符 */
Print(preItem);
Print(Space);
}else{
/* 若前一个运算符优先级低于当前运算符优先级,则弹入堆栈中等待并退出比较 */
Push(S, preItem);
//Tag 标记行
break;
}
}
/* while循环若是因为堆栈空退出,则不会将当前运算符弹入堆栈中等待
所以 Push(S, thisItem)不能放在Tag标记行中 */
Push(S, thisItem);
}
}
int main(){
ElementType item;
Stack* S;
S = CreateStack();
while(Scan(item)){
/* 区分读入的是运算数还是运算符 */
if(IsNumber(item)){
Print(item);//是运算数则直接输出
}else{
Print(Space);
PK(S, item);//是运算符则进行优先级比较
}
}
/* 输出堆栈内的剩余运算符 */
while(!IsEmpty(S)){
Print(Space);
item = Pop(S);
Print(item);
}
puts("");
return 0;
}