栈的应用——中缀表达式转后缀表达式并求值

栈的一些功能函数,这边用到的是链式栈。

typedef char ElemType;

//结点的信息
struct node
{
	ElemType data;          //数据域
	struct node *next;      //指针域
};
typedef struct node Node;  

//栈的信息
struct stack
{
	Node *top;                //头指针
	int count;                //结点个数
};
typedef struct stack  Stack;
//初始化
int StackInit(Stack **s)
{
	(*s) = (Stack *)malloc(sizeof(Stack) * 1);
	(*s)->top = NULL;
	(*s)->count = 0;
}
//初始化只要分配栈信息结构体的空间,结点的空间等到进栈的时候再分配。

//进栈:
int push(Stack **s, ElemType e)
{
	Node *p = (Node *)malloc(sizeof(Node));  //给结点分配空间
	p->data = e;    //数据域
	p->next = (*s)->top;
	(*s)->top = p;
	(*s)->count++;
}

//出栈:
int pop(Stack **s)
{
	Node *p = (*s)->top;
	ElemType e = (*s)->top->data;
	(*s)->top = (*s)->top->next;
	(*s)->count--;
	free(p);
}

 首先定义两个栈,一个叫s_num用来存放操作数,另一个叫s_opt用来存放操作符。

再定义一个字符数组用来存放输入的表达式,初始化为0;

当表达式的字符不为‘/0’时,或者操作符栈中不为空的时候,就要一直执行程序!

在执行的时候做两个判断,输入的不是数字就是操作符,当输入数字的时候进栈就可以了,并且i++,遍历下一个。

当遇到操作符时:有三种情况

一、入栈的情况:(入栈结束后,i++,遍历下一个输入字符)

1.操作符栈为空的时候。

2.操作符的优先级大于栈顶元素的时候。

3.当栈顶元素为’(‘时,并且输入不为')'时。

二、出栈不计算(结束后,i++,遍历下一个字符)

1.操作符出栈不计算的情况只有一种情况就是“(  ”操作符出栈的时候。

当输入为“  )”时,并且栈顶为“(  ”时,就是两个符号相遇时,出栈“(  ”并不计算。

三、出栈计算(计算完将数字存入s_num中就可以了,不需要遍历下一个字符)

将输入的字符与栈顶元素比较,满足情况的话将栈顶元素出栈,并取num栈中的数字进行运算,这是不需要i++,遍历下一个输入字符,break后再将输入的字符与栈顶元素比较,判断是入栈还是出栈!!!

1.输入的操作符为"/0"的时候,并且操作符栈不为空的时候,要将操作符中的所有元素出栈运算。

2.输入的操作符优先级小于或等于栈顶元素时。

3.当输入的字符为“  )”时,并且栈顶元素不为“(  ”时。

#include <stdio.h>
#include "LinkStack.h"

int Priority(char ch)
{
	switch(ch)
	{
		case '(':
			return 3;
		case '*':
		case '/':
			return 2;
		case '+':
		case '-':
			return 1;
		default:
			return 0;
	}
}

int main()
{
	Stack *s_opt, *s_num;
	char opt[1024] = {0};   //存放表达式
	int i = 0, tmp = 0, num1 = 0, num2 = 0;

	if (StackInit(&s_opt) != SUCCESS || StackInit(&s_num) != SUCCESS)
	{
		printf("Init Failure!\n");
	}

	printf("Please input : \n");
	scanf("%s", opt);

	while (opt[i] != '\0' || StackEmpty(s_opt) != TRUE)  //表达式没结束 或者 操作符栈不为空 一直执行这个循环
	{
	//输入的时候不是数字就是操作符分两次判断
		if (opt[i] >= '0' && opt[i] <= '9')    //当输入为数字的时候
		{
			tmp = tmp * 10 + opt[i] - '0';
			i++;
			if (opt[i] > '9' || opt[i] < '0')   //如果数组后面为操作符时直接入栈,但是如果数字后面还是数字的话就是两位数
			{
				push(&s_num, tmp); //入栈 写入到接受数字的那个栈
				tmp = 0;
			}
		}
		else       //如果输入是操作符 分三种情况
		{	
			if (opt[i] == ')' && GetTop(s_opt) == '(')    
				//1.操作符直接出栈不计算 当输入遇到‘)’时,并且栈顶为‘(’时
			{
				pop(&s_opt);
				i++;
				continue;
			}

			if (StackEmpty(s_opt) == TRUE || (Priority(opt[i]) > Priority(GetTop(s_opt))) 
				|| (GetTop(s_opt) == '(' && opt[i] != ')'))   
			//2.操作符进栈,三种可能
                1)操作符栈为空的时候,
                2)操作符优先级大于栈顶的时候,
                3)栈顶为‘(’时任何操作符都能进栈,除了‘)’!
			{
				push(&s_opt, opt[i]);
				i++;
				continue;
			}

			if ((opt[i] == '\0' && StackEmpty(s_opt) != TRUE) || 
				(opt[i] == ')' && GetTop(s_opt) != '(') || 
				(Priority(opt[i]) <= Priority(GetTop(s_opt))))  
				//3.操作符出栈平取操作数栈的前两个进行计算,三种可能
1)当表达式输入结束接收到字符'\0'时并且操作符栈不为空的时候,这时候要将操作符栈出光,
2)输入遇到字符‘)’时,栈顶不为‘(’时,
3)当输入操作符的优先级小于等于栈顶操作符优先级的时候
			{
				switch(pop(&s_opt))
				{
					case '+':
						num1 = pop(&s_num);
						num2 = pop(&s_num);
						push(&s_num, (num1 + num2));
						break;
					case '-':
						num1 = pop(&s_num);
						num2 = pop(&s_num);
						push(&s_num, (num2 - num1));
						break;
					case '*':
						num1 = pop(&s_num);
						num2 = pop(&s_num);
						push(&s_num, (num1 * num2));
						break;
					case '/':
						num1 = pop(&s_num);
						num2 = pop(&s_num);
						push(&s_num, (num2 / num1));
						break;
				}
			}
		}
	}

	printf("%d\n", GetTop(s_num));
	return 0;
}

猜你喜欢

转载自blog.csdn.net/sinat_39440759/article/details/81531614