中缀表达式转换为后缀表达式并求值(栈的使用)


 中缀表达式如2*3+(4-3), 其运算符一般出现在操作数之间, 因此称为中缀表达式,也就是大家编程中写的表达

式。编译系统不考虑表达式的优先级别, 只是对表达式从左到右进行扫描, 当遇到运算符时, 就把其前面的两

个操作数取出, 进行操作。为达到上述目的, 就要将中缀表达式进行改写,变为后缀表达式 如上面的表达式

2*3+(4-3), 就变为2 3 * 4 3 - + ;

后缀表达式中不含有括号, 且后缀表达式的操作数和中缀表达式的操作数排列次序完全相同, 只是运算符的

次序发生了改变。我们实现的时候,只需要用一个特定工作方式的数据结构(栈),就可以实现。

其中stack op;用来存放运算符栈。数组ans用来存放后缀表达式。

算法思想:

从左到右扫描中缀表达式,是操作数就放进数组ans的末尾。

如果是运算符的话,分为下面3种情况:

1)如果是‘(’直接压入op栈。

2)如果是‘)’,依次从op栈弹出运算符加到数组ans的末尾,知道遇到'(';

3) 如果是非括号,比较扫描到的运算符,和op栈顶的运算符。如果扫描到的运算符优先级高于栈顶运算符

则,把运算符压入栈。否则的话,就依次把栈中运算符弹出加到数组ans的末尾,直到遇到优先级低于扫描

到的运算符或栈空,并且把扫描到的运算符压入栈中。

就这样依次扫描,知道结束为止。

如果扫描结束,栈中还有元素,则依次弹出加到数组ans的末尾,就得到了后缀表达式。

下面是程序代码和问题描述:

问题描述:
请编写程序将一个中缀表达式转换为后缀表达式。
输入
仅一行,是一个中缀表达式。输入的符号中只有这些基本符号“0123456789+-*/()”,并且不会出现形如2*-3的格式,所有数字都是个位数,“/”表示整除运算。
输出
仅一行,是转换后的后缀表达式。数字之间、运算符之间、数字和运算符之间都用一个空格隔开(参见样例)。
样例
.in
8-(3+2*6)/5+4
.out
8 3 2 6 * + 5 / - 4 +


以下附全部代码

/*
 * =====================================================================================
 *
 *       Filename:  math.c
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  2013年09月12日 22时45分49秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  gaoyuan, 
 *        Company:  Class 1204 of Computer Science and Technology
 *
 * =====================================================================================
 */

#include 
#include 
#include 
#include 
#include 

#define MAXSIZE 100

typedef struct number
{
	int num[MAXSIZE];
	int len;
}Number;

typedef struct operate
{
	char operate[MAXSIZE];
	int len;
}Operate;

int empty_num(Number *s)
{
	if (s->len == -1)
	{
		return 1;
	}

	return 0;
}

int push_num(Number *s, int x)
{
	if (s->len == MAXSIZE - 1)
	{
		return 0;
	}
	else
	{
		s->len++;
		s->num[s->len] = x;
		return 1;
	}
}

int pop_num(Number *s, int * data)
{
	if (empty_num(s) == 1)
	{
		return 0;
	}
	else 
	{
		*data = s->num[s->len];
		s->len--;
		return 1;
	}
}

int top_number(Number *s, int *data)
{
	if (empty_num(s) == 1)
	{
		return 0;
	}

	else 
	{
		*data = s->num[s->len];
		return 1;
	}
}
Number * init_number()
{
	Number *m;

	m = malloc(sizeof(Number));
	m->len = -1;

	return m;
}

int empty_operate(Operate *s)
{
	if (s->len == -1)
	{
		return 1;
	}

	return 0;
}

int push_operate(Operate *s, char oper)
{
	if (s->len == MAXSIZE - 1)
	{
		return 0;
	}

	else
	{
		s->len++;
		s->operate[s->len] = oper;
		return 1;
	}
}

int pop_operate(Operate *s, char *oper)
{
	if (empty_operate(s) == 1)
	{
		return 0;
	}

	else 
	{
		*oper = s->operate[s->len];
		s->len--;
		return 1;
	}
}

char top_operate(Operate *s)
{
	if (s->len == -1)
	{
		return 'n';
	}

	else
	{
		return s->operate[s->len];
	}
}

Operate * init_operate()
{
	Operate *m;

	m = malloc(sizeof(Operate));
	m->len = -1;

	return m;
}

int if_operte(char c)
{
	if (c == '*' || c == '+' || c == '-' || c == '/' || c == '(' || c == ')')
	{
		return 1;
	}

	return 0;
}

int level(char a)
{
	if (a == '+' || a == '-')
	{
		return 1;
	}

	else if (a == '*' || a == '/')
	{
		return 2;
	}

	else if (a == '(' || a == ')')
	{
		return 3;
	}

	else if (a == '=')
	{
		return 0;
	}
}

int judge_level(char a, char b)
{
		return (level(a) - level(b));
}
void translate(char * quest, char * ans ,int n)
{
	Operate *tmp;
	char c;

	tmp = init_operate();
	push_operate(tmp, '=');

	while (n--)
	{
//		printf("%c\n", *quest);
		if ((*quest) >= '0' && (*quest) <= '9')
		{
			*ans++ = *quest;
		}

		else if ((*quest) == '(')   //如果是(,直接压栈
		{
			push_operate(tmp, (*quest));
		//	printf("ya %c\n", top_operate(tmp));
		}

		else if ((*quest) == ')')  //如果是),弹栈到数组,直到遇到(
		{
			while (top_operate(tmp) != '(')
			{
				pop_operate(tmp, &c);
				*ans++ = c;
		//		printf("c = %c\n", c);
				*ans++ = ' ';
		//		printf("ding %c %d\n", top_operate(tmp), tmp->len);
		//		getchar();
			}
			pop_operate(tmp, &c);
		}

		else if (if_operte(*quest) == 1)
		{
			if (top_operate(tmp) == '(')
			{
				push_operate(tmp, *quest);
			}

			else if (judge_level(*quest, top_operate(tmp)) > 0)  //如果扫描到的运算符优先级高于栈顶优先级,将运算符压栈
			{
				push_operate(tmp, *quest);
			}

			else if (judge_level(*quest, top_operate(tmp)) <= 0)  //如果扫描到的运算符优先级低于或等于栈顶优先级,依次弹出栈顶元素到数组,直到遇到优先级比扫描到的优先级低的
			{
				while (judge_level((*quest), top_operate(tmp)) <= 0 && (top_operate(tmp) != '='))
				{
					pop_operate(tmp, &c);
		//			printf("tan %c\n", c);
					*ans++ = c;
					*ans++ = ' ';
			//		*ans++ = *quest;
				}
				push_operate(tmp, *quest);
		//		printf("栈顶%c\n", top_operate(tmp));

			}
		}

		if (( if_operte(*quest)  == 0) &&  (if_operte(*(quest + 1)) == 1))
		{
			*ans++ = ' ';
		}
		quest++;
	}

//	printf("剩余%d\n", tmp->len);
	while (tmp->len != 0)
	{
		pop_operate(tmp, &c);
		*ans++ = c;
		*ans++ = ' ';
	}

	*ans = '\0';
}

int calculate (int num1, int num2, char ope)
{
	int result;
	
	switch (ope)
	{
		case '*':
			result = num1 * num2;
			break;
		case '/':
			result = num1 / num2;
			break;
		case '+':
			result = num1 + num2;
			break;
		case '-':
			result = num1 - num2;
			break;
	}

	return result;
}

void result (char * string, int n)
{
	char exp;
	char *p;
	int num, num3;
	int num1, num2;
	int i = 0, j = 0;
	int flag = 0;
	int tmp[MAXSIZE];
	char ope[MAXSIZE];
	Operate *operate;
	Number  *number;


	operate = init_operate();
	number  = init_number();
	p = string;

	while (*p != '\0')
	{
		num = 0;
		flag = 0;


		while ((*p) >= '0' && (*p) <= '9')
		{
			flag = 1;
			num = (*p - '0') + num * 10;
			p++;
		}

		if (flag == 1)
		{
			tmp[i++] = num;
			push_num(number, num);
		//	printf("压栈%d大小%d\n", num, number->len);
		}

		if (if_operte(*p) == 1)
		{
			pop_num(number, &num1);
			pop_num(number, &num2);


		//	printf("弹出%d %d\n", num1, num2);
		//	printf("还剩%d\n", number->len);
			push_num(number, calculate(num2, num1, *p));
			top_number(number, &num3);
		///	printf("%d %c %d = %d\n", num2, *p, num1, num3);
		//	printf("压栈%d\n", calculate(num2, num1, *p));
		
		}

		p++;
	}

	top_number(number, &num);
	printf("结果是%d\n", num);

}

int main(int argc, char *argv[])
{
	char string1[100];
	char string2[100];

	char *p, *q;

	printf("请输入\n");
	scanf("%s", string1);
//	printf("%s\n", string1);
	string1[strlen(string1)] = '\0';
//	printf("完了\n");

	p = string1;
	q = string2;

	translate(p, q, strlen(string1));

	printf("后缀表达式为\n%s\n", string2);
	string2[strlen(string2)] = '\0';

	result(string2, strlen(string2));


	return EXIT_SUCCESS;
}



你可能感兴趣的:(常见问题,数据结构,数据结构,栈)