栈在表达式计算过程中的应用 :建立操作数栈和运算符栈。运算符有优先级。规则:
自左至右扫描表达式,凡是遇到操作数一律进操作数栈。
当遇到运算符时,如果它的优先级比运算符栈栈顶元素的优先级高就进栈。反之,取出栈顶运算符和操作数栈栈顶的连续两个操作数进行运算,并将结果存入操作数栈,然后继续比较该运算符与栈顶运算符的优先级。
左括号一律进运算符栈,右括号一律不进运算符栈,取出运算符栈顶运算符和操作数栈顶的两个操作数进行运算,并将结果压入操作数栈,直到取出左括号为止。
二 表达式计算
//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;
}
运行结果如下: