表达式计算

栈的应用举例 :
栈在表达式计算过程中的应用 :建立操作数栈和运算符栈。运算符有优先级。规则: 
自左至右扫描表达式,凡是遇到操作数一律进操作数栈。
当遇到运算符时,如果它的优先级比运算符栈栈顶元素的优先级高就进栈。反之,取出栈顶运算符和操作数栈栈顶的连续两个操作数进行运算,并将结果存入操作数栈,然后继续比较该运算符与栈顶运算符的优先级。

左括号一律进运算符栈,右括号一律不进运算符栈,取出运算符栈顶运算符和操作数栈顶的两个操作数进行运算,并将结果压入操作数栈,直到取出左括号为止。

二 表达式计算

 

//1+3*5

char buf[1024];

 

第一步:

创建两个栈 operand_stack,operator_stack

 

第二 :

扫描表达式

 

操作数入栈的规则:直接入栈

push_stack(operator_stack,*p - '0');

 

运算符入栈的规则:

1.栈为空

2.当前运算符level > 栈顶运算符 level

 

提示:

int get_level(char operator)

{

switch(operator)

{

case '+':

case '-':

return 1;

case '*':

case '/':

return 2;

 

defalut:

printf("Invalid operator : %c.\n",operator);

return -1;

}

}

 

注意:

1.如果不满足运算符入栈的条件,就计算,一直到满足入栈条件为止

 

int compute(LinkStack *opd_s,LinkStack *opt_s)

{

int data,data1,data2;

 

switch(pop_stack(opts))

{

case '+':

data2 = pop_stack(opd_s);

data1 = pop_stack(opd_s);

data = data1 + data2;

push_stack(data,opd_s);

break;

.....

}

}

 

2.扫描结束的时候,需要判断运算符的栈是否为空

  不为空则计算

 

最后的结果放在操作数的栈


例如 :计算 ( 4+8 )×2-3 ;
操作数栈 :4  8     | 12      2|24     3|21
运算符栈 :( +                  |-        |


代码如下:

head.h

#ifndef _HEAD_H_

typedef int DATATYPE;

//栈中数据节点类型
typedef struct node 
{
	DATATYPE data;
	struct node *next;
}LinkNode;

//栈头类型
typedef struct 
{
	LinkNode *top;//记录栈顶元素节点的地址
	int n;//栈中数据的个数
}LinkStack;

extern LinkStack *create_empty_linkstack();
extern int is_empty_linkstack(LinkStack *s);
extern int push_linkstack(LinkStack *s,DATATYPE data);
extern DATATYPE pop_linkstack(LinkStack *s);
extern DATATYPE get_top_linkstack(LinkStack *s);

#endif 
linkstack.c

#include <stdio.h>
#include <stdlib.h>
#include "head.h"

LinkStack *create_empty_linkstack()
{
	LinkStack *s;

	s = (LinkStack *)malloc(sizeof(LinkStack));
	s->top = NULL;
	s->n   = 0;

	return s;
}

int is_empty_linkstack(LinkStack *s)
{
	return s->top == NULL ? 1 : 0;
}

int push_linkstack(LinkStack *s,DATATYPE data)
{
	LinkNode *temp;

	temp = (LinkNode *)malloc(sizeof(LinkNode));
	temp->data = data;

	//用新节点保存栈顶的地址
	temp->next = s->top;

	//用s->top记录新栈顶的地址
	s->top     = temp;
	
	//更新n的值
	s->n ++;

	return 0;
}

DATATYPE pop_linkstack(LinkStack *s)
{
	DATATYPE data;
	LinkNode *temp;

	//获得栈顶元素的地址
	temp = s->top;

	//让s->top保存栈顶元素的下一个节点地址
	s->top = temp->next;
	
	//获得栈顶的值
	data = temp->data;

	//释放栈栈顶的节点
	free(temp);

	//更新n 
	s->n --;

	return data;
}

DATATYPE get_top_linkstack(LinkStack *s)
{
	return s->top->data;
}
main.c

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

int get_operator_level(int operator)
{
	switch(operator)
	{
	case '(':
		return 0;

	case '+':
	case '-':
		return 1;

	case '*':
	case '/':
		return 2;

	default:
		printf("Invalid operator:%c\n",operator);
		return -1;
	}
}

int calc(LinkStack *opt_stack,LinkStack *opd_stack)
{
	int value;
	int data1,data2;

	switch(pop_linkstack(opt_stack))
	{
	case '+':
		data2 = pop_linkstack(opd_stack);
		data1 = pop_linkstack(opd_stack);
		value = data1 + data2;
		push_linkstack(opd_stack,value);
		break;

	case '-':
		data2 = pop_linkstack(opd_stack);
		data1 = pop_linkstack(opd_stack);
		value = data1 - data2;
		push_linkstack(opd_stack,value);
		break;

	case '*':
		data2 = pop_linkstack(opd_stack);
		data1 = pop_linkstack(opd_stack);
		value = data1 * data2;
		push_linkstack(opd_stack,value);
		break;

	case '/':
		data2 = pop_linkstack(opd_stack);
		data1 = pop_linkstack(opd_stack);
		value = data1 / data2;
		push_linkstack(opd_stack,value);
		break;
	}

	return 0;
}

int deal_with_operator(LinkStack *opt_stack,int operator,LinkStack *opd_stack)
{
	int current_level = get_operator_level(operator);

	//运算可以进栈的条件
	//1.运算符栈为空
	//2. current operator level > top stack operator level
	
	//处理不能进栈的条件
	while(!is_empty_linkstack(opt_stack) && current_level\
		<= get_operator_level(  get_top_linkstack(opt_stack)  ) )
	{
		calc(opt_stack,opd_stack);
	}

	push_linkstack(opt_stack,operator);

	return 0;
}

int calc_expression(char *string)
{
	char *p;
	int data = 0;
	LinkStack *opd_stack = create_empty_linkstack();
	LinkStack *opt_stack = create_empty_linkstack();

	//123+3*4-51\0
	for(p = string; *p != '\0';p ++)
	{
		if(*p >= '0' && *p <= '9')
		{
			data = 0;
			while(*p >= '0' && *p <= '9')
			{
				data = data * 10 + *p - '0';
				p ++;
			}

			push_linkstack(opd_stack,data);
		
		}

		switch(*p)
		{
		case '+':
		case '-':
		case '*':
		case '/':
			//处理运算符号
			deal_with_operator(opt_stack,*p,opd_stack);
			break;

		case '(':
			//左括号直接进栈
			push_linkstack(opt_stack,*p);
			break;

		case ')':
			//找左括号
			while(get_top_linkstack(opt_stack) != '(')
			{
				calc(opt_stack,opd_stack);
			}
			
			//出左括号
			pop_linkstack(opt_stack);
			break;

		case '\0':
			goto next;
		}
	}

next:
	//判断运算符的栈是否为空,不为空则计算
	while(!is_empty_linkstack(opt_stack))
	{
		calc(opt_stack,opd_stack);
	}

	return pop_linkstack(opd_stack);
}

int main(int argc, const char *argv[])
{
	int value;
	char buf[1024];

	printf("Input expression : ");
	scanf("%s",buf);
	
	value = calc_expression(buf);

	printf("%s = %d\n",buf,value);

	return 0;
}
运行结果如下:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值