中缀表达式转后缀表达式(堆栈 · 数据结构)

这是用堆栈的方式建立中缀表达式转后缀表达式的代码,这个代码我打了很久,一开始是在优酷上通过一个视频有关的思路讲解打出来的。


#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#define MAXSIZE 20
#define STACKINCREMENT 10

typedef struct SNode *PtrToSNode;
struct SNode
{
	char *date;
	int Top;
	int Base;
	int MaxSize;
};
typedef PtrToSNode Stack;

Stack CreatStack(int MaxSize)
{
	Stack S = (Stack)malloc(sizeof(struct SNode));
	S->date = (char *)malloc(MaxSize*sizeof(char));
	S->Top = S->Base;
	S->MaxSize = MaxSize;
	return S;
}

void Push( Stack S, char X )
{   
    //增加内存 
	if( S->Top - S->Base >= S->MaxSize )
	{
		S->date = (char *)realloc(S->date, (S->MaxSize + STACKINCREMENT )*sizeof(char));
		if(!S->date)
		exit(0);
		
		S->Top = S->Base + S->MaxSize;
		S->MaxSize = S->MaxSize + STACKINCREMENT;
	}	
	S->date[(S->Top)++] = X;
  //  printf("\nS->Top=%d 符号为:%c\n",S->Top-1, S->date[S->Top-1] );
}
int StackLen(Stack S)
{
    return (S->Top-S->Base); 
}
char Pop(Stack S) 
{
	if( S->Top == S->Base )
	return 0;
//	printf("\n出来时 S->Top=%d 符号位:%c\n", S->Top-1, S->date[S->Top-1]);
	return (S->date[--S->Top]);
}

int main()
{
	Stack S;
	char c, k;
	S = CreatStack(MAXSIZE);
	printf("输入中缀表达式:");
	scanf("%c", &c);
	printf("后缀表达式为:");     
	while( c!='\n' )
	{       
		while( c>='0' && c<='9' )
		{   
			printf("%c", c);
			scanf("%c", &c);
			if( c<'0'||c>'9')
			printf(" ");
		}
		if( ')' == c )
        {
        	k = Pop(S);
        	while( '(' != k )
        	{
        		printf("%c ", k);
        		k = Pop(S);
        	}
        }
		else if( '+' == c || '-' == c )
        {	
             if(!StackLen(S))
			 Push(S, c);
        	 else
        	 {
        	 	do
        	 	{
    	 		 k = Pop(S);
    	 		 if( '(' == k )
    	 		 {
    	 		  Push(S, k);//-->在这里不能用c,要用k重新将'('符号收回栈中 
    	 		 }
    	 		 else
    	 		 {
    	 		  printf("%c ", k);
    	 		 }
        	 	}while( StackLen(S) && '(' != k );
        	 	Push(S, c);
        	 }
        }
		else if( '*'==c || '/'==c || '('==c)
        {
        	Push(S, c);
        }
        else if('\n' == c)
        break;
		else
        {
        	printf("\n输入错误: 输入格式错误!\n");
        	return -1;
        }
		scanf("%c", &c);
	}
	while(StackLen(S))
	{
		k = Pop(S);
		printf("%c ", k);
	}
	return 0;
} 
//1+2*(2+3)-8/2

那就在这里详细说说中缀表达式转后缀表达式的具体思路:

1)第一次先遇见 ‘1’,直接输出,接着遇见符号‘+’,直接压入栈中:



2)第二次遇到数字‘2’的时候直接输出,输出后遇到‘ * ’符号,再次压入栈中,如下图:



3)在第二步后,后面的步骤也是相同的,但我们并不是一直把所有符号都收入栈中,如果有开括号,就要再一直压入栈中,直到遇到收括号,这时不必将收括号压入栈中,把括号中的符号和开括号前面的符号全部弹出了,入下图:



4)需要注意的是括号要避开输出,而这段代码里面可能有人不一定理解 if(‘+’||‘-’)这个条件里面的代码:

else if( '+' == c || '-' == c )
        {
             if(!StackLen(S))//当栈中为空的时候将遇到的加减符号直接压入栈中
Push(S, c);
        else
        {
        do
        {
    k = Pop(S);
    if( '(' == k )
    {
     Push(S, k); //-->在这里不能用c,要用k重新将'('符号收回栈中 ,好吧,这里也是我自己打错的地方,找了好久
    }
    else
    {
     printf("%c ", k);
    }
        }while( StackLen(S) && '(' != k );
        Push(S, c);
        }

        }

上面的do{}while();循环可能理解上有些难,不过解释前先强调一下,你要明白后缀表达式的输出规则是什么,当遇到括号里面有大量的加减乘除,例如2*(2+3+4+5+6+7-8-9)/2 ,输出为:2 2 3 + 4 + 5 + 6 + 7 + 8 - 9 - 2 /  *,要注意到括号里面的t弹出为首先是2 3 +,在这之后的弹出为4 +4后面弹出的‘+’号是4前面的符号,也就是说,当栈中连续第二次碰到加减符号,就必须要把前面的‘+’或‘-’符号弹出,于是在第一次弹出‘+’或‘-’符号后,在括号前停止输出,便有条件:while( StackLen(S) && '(' != k ); 同时我们用的是do while循环,他会先执行,后判断条件,这样一来就会导致‘(’开括号符号被弹出,于是便有 if( '(' == k )Push(S, k); 为的是将被弹出的‘(’开括号符号重新压入栈中,你可能想说直接用while()不好么,emmmmmmm, 你可以用我的代码直接试一下就明白了,你不还得判断有没有遇到‘(’开括号吗?那怎么遇到的?不就是将它弹出吗。。。而且弹出后不还得接着把它压回去, 而在while语句执行完毕后,就要把一开始遇到的符号压入栈中,便有 Push(S, c); 所以解释道这里,应该能明白这段代码的意思了吧。  

最后就是必须要提醒的是,当我们把括号中所有的符号输出后,还会有括号前面的符号压在栈中,于是我们在括号后就要一口气弹出所有的剩余符号,于是就有下面的代码:

while(StackLen(S))
{
k = Pop(S);
printf("%c ", k);
}
 

那么到了这里,这段代码的解释就全部结束了。

编译器用DEV C++


阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页