前缀中缀后缀表达式及其互相转换

计算机中前缀中缀后缀表达式是数据结构栈的重要应用,他们都是对表达式的记法,只是相对位置不一样,顾名思义,前缀表达式指的是符号都在操作数之前,中缀表达式指的是运算符都在操作数之后,而后缀表达式是之后。如:

(a+b)*c-d是中缀表达式

-*+abcd是前缀表达式

ab+c*d-是后缀表达式

中缀表达式是我们常用也是人常见的一种记法,但对于计算机来说处理很复杂,一般都是先转换成前缀或者后缀表达式再进行计算。

一、利用后缀表达式求值:

计算机利用后缀表达式求值过程可分析如下:

以中缀(3+4)*5-6为例,转换成后缀是34+5*6-

从左向右扫描,遇到数字时,将数字压入栈,遇到运算符时候,把栈内前两个数字弹出,进行相应运算,并将计算结果入栈。重复直到表达式右端。

从左向右扫描。将数字3,4入栈;

遇见运算符+,弹出3,4,计算得7入栈

继续扫描,将5入栈

与运算符*,将7,5弹出计算,得35入栈

继续扫描,遇见6入栈

遇见运算符-,弹出两个35,6,计算得29入栈

到最右端,停止,所得结果29

下面关键就是如何把中缀表达式转换成后缀表达式:

1、初始化两个栈,运算符栈S1和数据栈S2

2、从左向右扫描中缀表达式,遇见数字直接入栈S2

3、遇见运算符,将比较运算符与S1栈顶运算符优先级

3-1、如果S1栈顶是空或者是或者是左括号则直接将遇见的运算符入栈S1

3-2、如果S1栈顶不是空也不是左括号,且遇见的运算符比S1内优先级要高,那么将该运算符直接入栈S1(注意转换为前缀表达式时是优先级较高或相同,而这里则不包括相同的情况)

3-3、如果S1栈顶是是右括号或者优先级更大。则将S1内运算符出栈到S2里,再转回3-1

4、遇见括号

4-1、如果是遇见左括号,那么左括号运算符直接入栈S1

4-2、如果是遇见右括号,那么右括号运算符直接入栈S1

5、重复2-4,直至到表达式最右边

6、将S1中剩余运算符弹出到S2

7、 依次弹出S2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式(转换为前缀表达式时不用逆序)。

将中缀表达式exp转换为后缀表达式,采用了一个op运算符栈,其他的用数组存储。

const int N=20;
vector inexpTopost(char a[],int n){
vector res;
char st[N];
int top=-1;
int i=0;
char c=a[i];
while(c!='\0'){
    switch(c){
    case '(':{top++;st[top]=c;break;}
    case ')':{while(st[top]!='('){res.push_back(st[top]);top--;}
             top--;
             break;
         }
    case '+':
    case '-':{while(top>-1&&st[top]!='('){res.push_back(st[top]);top--;}
             top++;st[top]=c;
             break;
         }
    case '*':
    case '/':{
          while(top>-1&&st[top]!='('&&(st[top]=='*'||st[top]=='/')){res.push_back(st[top]);top--;}
          top++;st[top]=c;
          break;
         }
    default:{
            while(c>='0'&&c<='9')
            {res.push_back(c);i++;c=a[i];}//装入多位的整数
            i--;
            res.push_back('#');//用标识表述数值结束
         }
              }
    i++;c=a[i];
               }
while(top>-1){res.push_back(st[top--]);}
return res;
}

在计算后缀表达式过程中采用一个数值栈st:

float getkey_post(vector arr){
int num_stack[N];int top1=-1;
int len=arr.size();
int i=0;
char c=arr[i];
int s=0;
while(i='0'&&c<='9'){s=10*s+c-'0';i++;c=arr[i];}
          top1++;num_stack[top1]=s;i--;
          }
            } 
  i++;
              }
return num_stack[top1];
}


二、利用前缀表达式求值

以中缀(3+4)*5-6为例,转换成前缀是-*+3456

利用前缀表达式求值:从右向左搜索,遇见数字时入栈,遇见运算符时候出栈前两个数字3+4=7,计算好7再入栈,遇见运算符*,出栈前两个进行计算7*5=35,再入栈,遇见运算符-,出栈进行运算35-6=29,入栈保存结果。

将中缀表达式转换为前缀的过程:

1、初始化两个栈,运算符栈S1和数据栈S2

2、从右向左扫描中缀表达式,遇见数字直接入栈S2

3、遇见运算符,将比较运算符与S1栈顶运算符优先级

3-1、如果S1栈顶是空或者是或者是又括号则直接将遇见的运算符入栈S1

3-2、如果S1栈顶不是空也不是左括号,且遇见的运算符比S1内优先级要高或者一样,那么将该运算符直接入栈S1。

3-3、如果S1栈顶是是左括号或者优先级更大。则将S1内运算符出栈到S2里,再转回3-1

4、遇见括号

4-1、如果是遇见右括号,那么左括号运算符直接入栈S1

4-2、如果是遇见左括号,那么右括号运算符直接入栈S1

5、重复2-4,直至到表达式最左边

6、将S1中剩余运算符弹出到S2

7、 依次弹出S2中的元素并输出,结果即为中缀表达式对应的前缀表达式。

vector inexpTopre(char a[],int n){
vector res;
char num_stack[N];int top1=-1;
char op_stack[N];int top2=-1;
int i=n-1;
char c=a[i];
while(i>=0){
    switch(c){
	case ')':{top2++;op_stack[top2]=c;break;}
	case '(':{while(op_stack[top2]!=')'){top1++;num_stack[top1]=op_stack[top2];top2--;}
		     top2--;
		     break;
		 }
	case '+':
	case '-':{while(top2>-1&&op_stack[top2]!=')'&&(op_stack[top2]=='*'||op_stack[top2]=='/')){top1++;num_stack[top1]=op_stack[top2];top2--;}
		  top2++;op_stack[top2]=c;
		  break;
		 }
	case '*':
	case '/':{top2++;op_stack[top2]=c;
		     break;
		 }
	default:{
		 while(c>='0'&&c<='9'){top1++;num_stack[top1]=c;i--;c=a[i];}
                top1++;num_stack[top1]='#';i++;
		}
              }
    i--;if(i<0)break;
    c=a[i];
              }
while(top2>-1){top1++;num_stack[top1]=op_stack[top2--];}
for(i=top1;i>=0;i--)
    res.push_back(num_stack[i]);
return res;
}
最后是根据前缀序列求出最终结果:

int getvalue(char str[]){
int s=0;
int i,j;
int len=0;
for(i=0;str[i]!='\0';i++)
   len++;
for(i=0,j=len-1;iarr){
int st[N],top=-1;
int len=arr.size();
int i=len-1,j;
char c=arr[i];
int s;
char tmp[N];
while(i>=0){
    c=arr[i];
    switch(c){
	case '+':{st[top-1]=st[top]+st[top-1];top--;break;}
	case '-':{st[top-1]=st[top]-st[top-1];top--;break;}
        case '*':{st[top-1]=st[top]*st[top-1];top--;break;}
	case '/':{
		     if(st[top-1]==0){cout<<"除数是0";return 0;}
                     st[top-1]=st[top]/st[top-1];top--;break;
		 }
	case '#':break;
	default:{
		    s=0;
		    j=0;
		    while(c>='0'&&c<='9'){tmp[j++]=c;i--;c=arr[i];}
		    tmp[j]='\0';s=getvalue(tmp);
		    top++;st[top]=s;i++;
		}

             }
    i--;
            }
return st[top];
}



你可能感兴趣的:(数据结构区)