您的位置:首页 > 理论基础 > 数据结构算法

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

2018-01-17 09:18 183 查看
本文解决的问题:

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存运算符
4000
,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
[m] == 1){
//新运算符优先级大于栈顶运算符,直接插入s1
push(*(p+i),&s1);
}else if(prior
[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
[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]
== 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]
== 1){
//新运算符优先级大于栈顶运算符,直接插入s1
push(*(p+i),&s1);
}else if(prior[m]
== 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]
== 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]
== 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;
}


如有疑问,请及时提出,谢谢!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: