栈的应用——加减乘除四则运算

栈的应用——加减乘除四则运算

栈是特殊的线性表,相较于一般的线性表,在定义结构体时多了栈顶指针这一元素(在链式表中为指针,在顺序表中表现为记录数组最后一个元素的下标的整型变量 int top)。栈的操作也有别于通常的线性表,主要是通过栈顶指针对栈顶元素进行修改,包括了入栈、出栈、取栈顶元素等操作。由于栈通过栈顶指针进行操作,栈中元素表现出“后进先出”的特点,在程序设计时的应用十分广泛,其中加减乘除四则运算就是一个典型的例子。

a[maxsize]栈顶指针
a[maxsize-1]
a[n]top(栈顶元素的下标)
a[2]
a[1]
a[0]
#define max1 100
#ifndef __MAX__K__
#define __MAX__K__
typedef struct {      //定义一个栈
	int a[max1];		  //栈内的整数数组
	char sym[max1];		//字符数组
	int topnum=;			//定义栈顶下标
	int topchar;
}stack;
#endif

栈的基本操作

入栈

判断栈知否满
栈不为满
栈顶指针top+1
元素入栈
栈满则返回error
a[maxsize]栈顶指针
a[maxsize-1]
a[n+1]top
a[n]
a[2]
a[1]
a[0]
void push(stack* p, int num) {		//num为输入的数值
	if ((p->topnum) < max1-1) {   //判断栈是否满
		p->topnum++;					//未满则最大下标+1
		int k = p->topnum;
		p->a[k] = num;				//赋值
	}
	else {
		printf("error\n");			//栈满则输出error
	}
}

出栈

判断栈知否空
栈不为空
栈顶指针top-1
栈空则返回error
a[maxsize]栈顶指针
a[maxsize-1]
a[n]
a[n-1]top
a[2]
a[1]
a[0]
int pop(stack* p) {						//出栈操作
	int i=0;
	if ((p->topnum) > -1) {
		i = p->a[p->topnum];			//i记录栈顶元素的数值
		p->topnum--;					//出栈之后下标减一
	}
	else {
		printf("error\n");
	}
	return i;

其他操作

由于其他操作也是在栈顶指针的基础上实现,这里就不一一叙述了。

加减乘除四则运算的实现

我们要写一段代码,实现加减乘除的运算,其实核心问题在于解决乘除运算的优先级高于加减的问题。利用上文所提到栈后进先出的特点,就可以解决这个问题。我们大致的思路如下:

首先定义两个栈,一个存放数值,一个存放运算符

开始
读入一个
数值
并入栈
读入一个
运算符
判断
运算符
若为加或减
将运算符入栈
若为乘或除
继续读入一个数
将栈顶数值出栈
二者进行乘或除运算
并将运算结果入栈
若为=
则循环结束

也就是说,在这个过程中,遇到乘或除会优先处理运算,并将其值入栈,而加减则会依次放入运算符栈中。即最后的结果是符号栈只剩下加减,而且在数值栈除a[0]外,每个数都有一个加或减与之对应。而a[0]在第一次读数时已自带正负,也就是说,剩下只需要进行加减运算即可。

核心问题到此以解决。

基于出、入栈的操作,下面补充运算函数用于计算:

int num_op(int x, char i, int y) {
	int j = 0,num=0;
	if (i == '+') {
		num = x + y;
	}
	if (i == '-') {
		num = x - y;
	}
	if (i == '*') {
		num = x * y;
	}
	if (i == '/') {
		num = x / y;
	}
	return num;
}

int num_tran(int x, char i) {		//数值的转换,若数值对应的运损符
									//为-,令其等于其相反数;反之不变
	if (i == '-') {
		x = -x;
	}
	return x;
}

以下为主函数(其中 pushchar 与 popchar 分别为运算符入栈、出栈的函数):

	char m,n;   //m读入符号
	int num1,all = 0; //all记录整个式子的值
	stack* p = (stack*)malloc(sizeof(stack));	
	if (p) {			//判断p是否正常申请
		p->topchar = -1;  //初始化栈顶指针下标
		p->topnum = -1;

		while (1) {
			scanf_s("%d", &num1);		//读入一个数
			push(p, num1);				//num1入栈
			scanf_s("%c", &m,1);			//读入运算符至m
			__after_1_:
			if (m == '=') {				//读入 = 号则循环停止
				break;
			}
			if (m == '*' || m == '/') {		//读入*或/则读入下一个数并存至k1
				while (m == '*' || m == '/') {
					scanf_s("%d", &num1);	//读入下一个数
					int num2 = pop(p);		//取栈顶元素并存入num2
					num2 = num_op(num2, m, num1);	//num2与num1进行m运算并将运算值存入num2
					push(p, num2);			//进行乘或除运算后的值入栈
					scanf_s("%c", &m, 1);	//	继续读入一个运算符至m			
				}
				goto __after_1_;				//由于运算过程可能出现连续进行连续进行乘
											//或除运算的运算,所以这里要回到__after_1_的位置对m
											//的符号进行判断,若为*或/,继续进行
											//读数 -> 出栈 -> 运算值入栈   的操作
			}
			if(m=='+'||m=='-'){
				pushchar(p, m);					//若m为+或-,输入栈的字符数组
			}
		}
		//进行完以上操作后符号栈只剩下+或-,即待剩下的式子为a[0]至a[topnum]之间的+或-运算

		while (p->topnum > 0) {			//对a[0]之前的数进行操作
			n = popchar(p);				//为方便操作,这里同意把运算看成+
			all += num_tran(pop(p), n);	//通过定义num_tran函数转换。若a[n]对应的运算符为-
										//取a[n]为其相反数,即将变为 -a[n]的运算变成
										//  +(-a[n])
		}
	}
	all += pop(p);		//由于a[0]没有相应的运算符与之对应这里单独处理
	printf("result = %d", all);
	free(p);
	return 0;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值