数据结构之利用栈实现四则运算

本文解决的问题:

9. 使用堆栈功能实现字符串表达式的求值。(表达式指四则运算表达式)

本文利用的求解方法是:

(1)、将表达式转化成后缀表达式;

(2)、利用后缀表达式结合栈求结果。

而关于中缀、前缀、后缀表达式的理论以及相互转化的步骤,我之前参考了一篇博文,觉得还不错,给大家分享一下:前、后、中缀表达式

实现代码如下:

/*******************************9、使用堆栈功能实现字符串表达式的求值*************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

const int StackSize=100;//栈空间

typedef struct Stack
{
	char data[StackSize];
	int top;
}Stack;

void initStack(Stack *s)
{
	s->top=-1;
}

//匹配运算符
int mateChar(char s)
{
	int i;
	switch(s){
		case '+':i=0;break;
		case '-':i=1;break;
		case '*':i=2;break;
		case '/':i=3;break;
		case '(':i=4;break;
		case ')':i=5;break;
	}
	return i;
}


//入栈
void push(char x,Stack *s)
{
	if(s->top>=100)
	{
		printf("栈满!!\n");
	}else{
		s->top++;
		s->data[s->top] = x;
	}
}
//出栈
char pop(Stack *s)
{
	char x;
	if(s->top==-1){
		printf("栈为空!!\n");
		return '#';
	}else{
		x=s->data[s->top];
		s->top--;
	}
	return x;
}
//取运算符栈顶元素
char get_char(Stack *s)
{
	char x;
	if(s->top==-1){
		//printf("栈为空!!\n");
		return '#';
	}else{
		x=s->data[s->top];
	}
	return x;
}

//字符串数字转成数字
int tranform_num(char x)
{
	int i;
	i=x-'0';
	return i;
}
//数字转字符串
char tranfoe_char(int x)
{
	char s;
	s=x+'0';
	return s;
}

//输出栈内元素
void printf_stack(Stack *s)
{
	if(s->top == -1){
		printf("栈内无元素!!\n");
	}else{
		int temp=0;
		while(temp<=s->top)
		{
			printf("%c",s->data[temp]);
			temp++;
		}
		printf("\n");
	}
}

int calculate(int x,int y,char s)
{
	int i;
	switch(s){
		case '+':i=x+y;break;
		case '-':i=x-y;break;
		case '*':i=x*y;break;
		case '/':i=x/y;break;
	}
	return i;
}

//根据后缀表达式计算结果
int count(Stack *s,Stack *t)
{
	int temp=0;
	char count;
	//遍历存储后缀表达式的栈
	while(temp<=s->top){
		//获得栈顶元素
		char k=s->data[temp];
		if(k>='0'&&k<='9')
		{
			//如果是数字,进t栈
			push(k,t);
		}else{
			//如果是操作符,则计算
			int x=tranform_num(pop(t));
			int y=tranform_num(pop(t));
			int z=calculate(x,y,k);
			push(tranfoe_char(z),t);
		}
		temp++;
	}
	count=t->data[t->top];
	return tranform_num(count);
}


int main()
{
	Stack s1,s2;//s1存运算符,s2存最后结果
	char nums[100];
	int i;
	int length;
	char *p=nums;
	int prior[4][4]={{0,0,1,1},{0,0,1,1},{0,0,0,0},{0,0,0,0}};
	//初始化
	initStack(&s1);
	initStack(&s2);
	printf("请输入运算式,运算数为0-9:\n");
	scanf("%s",&nums);
	printf("您输入的是:%s\n",nums);
	length=(int)strlen(nums);
	/*************************************************转成后缀表达式********************************/
	//1、循环表达式 ,确定入栈和出栈
	for(i=0;i<length;i++)
	{
		//数字
		if(*(p+i)>='0'&&*(p+i)<='9')
		{
			push(*(p+i),&s2);
		}else{//运算符
			int m;//当前运算符位置
			int n;//栈顶元素运算符位置
			char k=get_char(&s1);
			if(k == '#')
			{
				//栈内为空,直接入栈
				push(*(p+i),&s1);
			}else{
				//栈内不为空,比较优先级
				m=mateChar(*(p+i));
				n=mateChar(k);
				if(prior[n][m] == 1){
					//新运算符优先级大于栈顶运算符,直接插入s1
					push(*(p+i),&s1);
				}else if(prior[n][m] == 0)
				{
					//新运算符优先级不大于栈顶运算符,将s1栈顶元素弹出,压入s2,继续比较新运算符和s1栈顶的优先级
					char temp=pop(&s1);
					push(temp,&s2);
					if(k=get_char(&s1) == '#')
					{
						push(*(p+i),&s1);
						continue;
					}else{
						while(prior[n][m] == 0)
						{
							char temp=pop(&s1);
							push(temp,&s2);
							k=get_char(&s1);
							n=mateChar(k);
						}
					}
					/*
					char temp=pop(&s1);
					push(temp,&s2);
					k=get_char(&s1);
					while(k != '#')
					{
						n=mateChar(k);
						if(prior[m][n] == 0){
							char temp=pop(&s1);
							push(temp,&s2);
							k=get_char(&s1);
						}else{
							push(*(p+i),&s1);
							break;
						}
					}
					*/
				}
			}
		}
	}
	char k=get_char(&s1);
	while(k != '#'){
		pop(&s1);
		push(k,&s2);
		k=get_char(&s1);
	}
	printf("此时后缀表达式为:\n");
	printf_stack(&s2);
	/*************************************************运用后缀表达式求结果********************************/
	int count_=count(&s2,&s1);
	printf("结果为:%d\n",count_);
	return 0;
}

-----------------------------------------------------------------------------------------------------------------

2018年1月18日更新,增加了对括号的识别

/*******************************9、使用堆栈功能实现字符串表达式的求值(括号和多位数)*************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

const int StackSize=100;//栈空间

typedef struct Stack
{
	char data[StackSize];
	int top;
}Stack;

void initStack(Stack *s)
{
	s->top=-1;
}

//匹配运算符
int mateChar(char s)
{
	int i;
	switch(s){
		case '+':i=0;break;
		case '-':i=1;break;
		case '*':i=2;break;
		case '/':i=3;break;
		case '(':i=4;break;
		case ')':i=5;break;
	}
	return i;
}


//入栈
void push(char x,Stack *s)
{
	if(s->top>=100)
	{
		printf("栈满!!\n");
	}else{
		s->top++;
		s->data[s->top] = x;
	}
}
//出栈
char pop(Stack *s)
{
	char x;
	if(s->top==-1){
		printf("栈为空!!\n");
		return '#';
	}else{
		x=s->data[s->top];
		s->top--;
	}
	return x;
}
//取运算符栈顶元素
char get_char(Stack *s)
{
	char x;
	if(s->top==-1){
		//printf("栈为空!!\n");
		return '#';
	}else{
		x=s->data[s->top];
	}
	return x;
}

//字符串数字转成数字
int tranform_num(char x)
{
	int i;
	i=x-'0';
	return i;
}
//数字转字符串
char tranfoe_char(int x)
{
	char s;
	s=x+'0';
	return s;
}

//输出栈内元素
void printf_stack(Stack *s)
{
	if(s->top == -1){
		printf("栈内无元素!!\n");
	}else{
		int temp=0;
		while(temp<=s->top)
		{
			printf("%c",s->data[temp]);
			temp++;
		}
		printf("\n");
	}
}

int calculate(int x,int y,char s)
{
	int i;
	switch(s){
		case '+':i=x+y;break;
		case '-':i=x-y;break;
		case '*':i=x*y;break;
		case '/':i=x/y;break;
	}
	return i;
}

//根据后缀表达式计算结果
int count(Stack *s,Stack *t)
{
	int temp=0;
	char count;
	//遍历存储后缀表达式的栈
	while(temp<=s->top){
		//获得栈顶元素
		char k=s->data[temp];
		if(k>='0'&&k<='9')
		{
			//如果是数字,进t栈
			push(k,t);
		}else{
			//如果是操作符,则计算
			int x=tranform_num(pop(t));
			int y=tranform_num(pop(t));
			int z=calculate(x,y,k);
			push(tranfoe_char(z),t);
		}
		temp++;
	}
	count=t->data[t->top];
	return tranform_num(count);
}


int main()
{
	Stack s1,s2;//s1存运算符,s2存最后结果
	char nums[100];
	int i;
	int length;
	char *p=nums;
	int prior[4][4]={{0,0,0,0},{0,0,0,0},{1,1,0,0},{1,1,0,0}};
	//初始化
	initStack(&s1);
	initStack(&s2);
	printf("请输入运算式(要求:不包含括号,数字范围为0-9):\n");
	scanf("%s",&nums);
	//printf("您输入的是:%s\n",nums);
	length=(int)strlen(nums);
	/*************************************************转成后缀表达式********************************/
	//1、循环表达式 ,确定入栈和出栈
	for(i=0;i<length;i++)
	{
		//数字
		if(*(p+i)>='0'&&*(p+i)<='9')
		{
			push(*(p+i),&s2);
		}else{//运算符
			int m;//当前运算符位置
			int n;//栈顶元素运算符位置
			char k=get_char(&s1);
			if(k == '#')
			{
				//栈内为空,直接入栈
				push(*(p+i),&s1);
			}else{
				//栈内不为空,比较优先级
				m=mateChar(*(p+i));
				n=mateChar(k);
				if(m == 4 || n == 4)
				{
					//若入栈的为(或者栈顶为(,则元素直接进栈;
					push(*(p+i),&s1);

				}else if(m == 5){
					//如果入栈元素为),则将符号栈内(之前的符号依次出栈,放入数字栈中
					char temp1=pop(&s1);
					while(temp1 != '(')
					{
						push(temp1,&s2);
						temp1=pop(&s1);
					}
				}else if(prior[m][n] == 1){
					//新运算符优先级大于栈顶运算符,直接插入s1
					push(*(p+i),&s1);
				}else if(prior[m][n] == 0)
				{
		//新运算符优先级不大于栈顶运算符,将s1栈顶元素弹出,压入s2,继续比较新运算符和s1栈顶的优先级
					char temp=pop(&s1);
					push(temp,&s2);
					if(k=get_char(&s1) == '#')
					{
						push(*(p+i),&s1);
						continue;
					}else{
						temp=pop(&s1);
						n=mateChar(temp);
						while(prior[m][n] == 0)
						{
							push(temp,&s2);
							k=get_char(&s1);
							if(k == '#')
							{
								break;
							}
							n=mateChar(k);
						}
						push(*(p+i),&s1);
					}
					/*
					char temp=pop(&s1);
					push(temp,&s2);
					k=get_char(&s1);
					while(k != '#')
					{
						n=mateChar(k);
						if(prior[m][n] == 0){
							char temp=pop(&s1);
							push(temp,&s2);
							k=get_char(&s1);
						}else{
							push(*(p+i),&s1);
							break;
						}
					}
					*/
				}
			}
		}
	}
	char k=get_char(&s1);
	while(k != '#'){
		pop(&s1);
		push(k,&s2);
		k=get_char(&s1);
	}
	printf("此时后缀表达式为:\n");
	printf_stack(&s2);
	/*************************************************运用后缀表达式求结果********************************/
	int count_=count(&s2,&s1);
	printf("计算出来的结果为:%d\n",count_);
	return 0;
}


如有疑问,请及时提出,谢谢!!

  • 5
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值