河北联合大学表达式遍历.docx

上传人:b****6 文档编号:6392220 上传时间:2023-01-06 格式:DOCX 页数:26 大小:220.43KB
下载 相关 举报
河北联合大学表达式遍历.docx_第1页
第1页 / 共26页
河北联合大学表达式遍历.docx_第2页
第2页 / 共26页
河北联合大学表达式遍历.docx_第3页
第3页 / 共26页
河北联合大学表达式遍历.docx_第4页
第4页 / 共26页
河北联合大学表达式遍历.docx_第5页
第5页 / 共26页
点击查看更多>>
下载资源
资源描述

河北联合大学表达式遍历.docx

《河北联合大学表达式遍历.docx》由会员分享,可在线阅读,更多相关《河北联合大学表达式遍历.docx(26页珍藏版)》请在冰豆网上搜索。

河北联合大学表达式遍历.docx

河北联合大学表达式遍历

数据结构(双语)

——项目文档报告

用两种方式实现表达式自动计算

 

专业:

计算机科学与技术

班级:

指导教师:

姓名:

学号:

 

目录

一、设计思想……………………………………………………….03

二、算法流程图…………………………………………………….04

三、源代码………………………………………………………….06

四、运行结果……………………………………………………….18

五、遇到的问题及解决…………………………………………….18

六、心得体会……………………………………………………….19

 

一、设计思想

本报告用两种算法分别对表达式进行计算:

一:

将用户所输入的中缀表达式先变换成后缀表达式,然后在对后缀表达式进行计算。

二:

将用户所输入的中缀表达式直接进行计算。

第一种算法:

这种算法又可分为两步:

第一步:

将用户输入的中缀表达式先转换成后缀表达式:

在这一步中,首先要建立一个符号栈,和一个字符串数组,接着读用户输入的字符,如果用户输入的是数字、+、—、*、/、%、(、)以外的字符,则程序报错。

如果读到的是数字或小数点,则直接放入字符串数组。

如果读到的是符号,则与符号栈栈顶的元素的优先级进行比较,如果当前读入的符号的优先级高,则直接入栈,如果当前符号的优先级低于栈顶元素的优先级,那么将栈顶元素弹出,并将其放入字符串数组中,如果读到的是左括号,则直接入栈,并将当前符号与栈中栈顶的下一个元素进行对比。

如果读到的是右括号,则观察栈顶元素,如果栈顶不为左括号或空,则将符号存入字符串数组中,如果遇到左括号,则弹出左括号,如果栈为空,则结束。

如此循环,直到遇到’\0’结束,最终字符串数组中的表达式为后缀表达式。

第二步:

对后缀表达式进行计算:

在这一步中,首先要建立一个数值栈,对字符串数组中的字符进行读取,当读取到数值时,将数值放入数值栈中,如果读到符号,则将弹出栈中的两个数字进行计算,在将计算结果放入数值栈中,最后栈中留下的结构就是表达式最后的结果。

第二种算法:

在此算法中要定义两个栈,一个叫数值栈,一个叫符号栈,将用户输入的字符逐个进行扫描,如果用户输入的是数字、+、—、*、/、%、(、)以外的字符,则程序报错。

如果是数字或小数点,则放入数值栈中,如果是符号,则先将此符号的优先级与符号栈的栈顶元素的优先级做比较,如果当前读到的符号的优先级比符号栈栈顶元素的优先级高,则此符号入栈。

如果此符号优先级低,则将栈顶元素出栈,然后从数值栈中弹出两个元素,将这两个元素进行计算,计算结果继续压入到数值栈中,而将当前读到的符号继续与符号栈中的下一个栈顶元素比较,如此循环,直到符号栈中栈顶元素的优先级小于或等于当前符号的优先级,则将当前符号压入符号栈中,如果读到的是左括号,则直接放入符号栈中,如果读到的是右括号,则从符号栈中弹出一个符号,从数值栈中弹出两个数字,然后将计算结果放入数值栈中,如此循环操作,如果遇到左括号,则停止,并释放左括号。

接着读取下一个字符,读取结束时,计算结果就放在数值栈中,从而将数值栈中的元素弹出即为所求结果。

 

二、算法流程图

第一个算法的流程图:

用户输入的中缀表达式

主函数的流程图:

存在错误并结束程序

判断表达式中是否含有除数字、+、—、*、/、%、(、)以外的字符

返回计算结果

 

调用函数将中缀表达式转换成后缀表达式

调用函数通过后缀表达式计算出结果

图1主函数流程图

中缀转化为后缀的流程图:

如果是除括号以外的操作符

如果是数字或小数点

读取用户输入的字符并判断

优先级高于栈顶

如果是括号

入栈

与栈顶元素比较

判断括号类型

优先级低于栈顶

将其放入字符数组中,并在后面加上分隔符

如果是右括号

如果是左括号

栈顶元素出栈存入数组中

直接入栈

从栈中取出操作符

放入数组中

取出的不是左括号

图2中缀转化为后缀流程图

后缀表达式计算的流程图

后缀表达式

如果是操作符

如果是数字

判断符号类型

 

从数值栈中取出两个数计算并将结果放入栈中

转化为浮点数入栈

图3后缀表达式计算流程图

第二种算法的流程图

用户输入的中缀表达式

主函数的流程图:

存在错误并结束程序

判断表达式中是否含有除数字、+、—、*、/、%、(、)以外的字符

返回计算结果

 

调用直接计算的函数

图4主函数流程图

直接计算函数的流程图:

转化为浮点数入数值栈

图4直接计算流程图

三、源代码

下面给出的是用中缀转后缀计算算法实现的程序的源代码:

#include/*导入需要用到的各种包*/

#include

#include

#include

typedefstruct/*定义结构体用来存储操作符*/

{

charop;/*存储字符*/

intlevel;/*存储优先级*/

}OpNode;

typedefstruct

{

OpNodeop[100];

inttop;

intsize;/*表示栈内元素的个数*/

}stack;/*定义符号栈*/

voidinit(stack*st)/*初始化栈*/

{

st->size=0;

st->top=0;

}

OpNodepop(stack*a)/*出栈*/

{

if(a->size==0)/*如果栈为空结束操作*/

{

exit(-1);

}

a->size--;

returna->op[--(a->top)];/*取出栈顶元素*/

}

voidpush(stack*a,OpNodeop)/*入栈函数*/

{

a->size++;

a->op[(a->top)++]=op;

}

OpNodetop(stack*a)/*观察栈顶函数*/

{

if(a->size==0)/*如果栈为空结束操作*/

{

printf("stackisempty\n");

exit(-1);

}

returna->op[(a->top)-1];/*只得到栈顶的值而不出栈*/

}

 

typedefstruct/*定义数值栈*/

{

doublenum[100];

inttop;/*栈顶指针*/

intsize;

}numstack;

voidinit2(numstack*st)/*初始化数值栈*/

{

st->size=0;

st->top=0;

}

doublepop2(numstack*a)/*数值栈出栈*/

{

if(a->size==0)/*出栈前的判空*/

{

exit(-1);

}

a->size--;

returna->num[--(a->top)];/*得到栈顶的值*/

}

voidpush2(numstack*a,doublenum)/*入栈*/

{

a->size++;

a->num[(a->top)++]=num;

}

voidmain()/*主函数*/

{

voidchange(charstr[],charexp[]);/*声明要用到的各个函数*/

doubleCalResult(charexp[]);/*声明后缀表达式的计算函数*/

charstr[100],exp[100];/*str存储原算术表达式,exp存储对应的printf("算术表达式为:

\n");后缀表达式,chestr存储容错字符'^'*/

printf("算术表达式为:

\n");

gets(str);

change(str,exp);/*调用函数将中缀转化为后缀*/

printf("后缀表达式为:

%s\n",exp);

printf("运算结果为:

%f\n",CalResult(exp));/*调用函数计算后缀表达式*/

inta;

scanf(&a);

}

voidchange(charstr[],charch[])/*将前缀表达式转化为后缀表达式*/

{

inti=0;/*str的索引*/

intk=0;

charc;/*字符串中取出的放在C中*/

stackst;/*定义符号栈*/

OpNodeop;

OpNodeops;

init(&st);/*初始化符号栈*/

c=str[i++];

while(c!

='\0')/*对字符串进行扫描*/

{

if((!

isdigit(c))&&(c!

='-')&&(c!

='+')&&(c!

='%')&&(c!

='/')&&(c!

='*')&&(c!

='(')&&(c!

=')')){

printf("输入字符的格式错误\n");

break;

}

if(isdigit(c)||c=='.')/*如果字符为数字或小数点*/

{

while(isdigit(c)||c=='.')

{

ch[k++]=c;/*将字符直接放入数组中*/

c=str[i++];

}

ch[k++]='|';/*在其后面放入一个分隔符*/

}

if(c=='(')/*如果字符是左括号*/

{

op.op='(';

op.level=-1;/*定义其优先级为-1*/

push(&st,op);/*将左括号直接入栈*/

}

if(c==')')/*如果字符为右括号*/

{

op=top(&st);/*首先观察栈顶*/

while(st.size!

=0&&op.op!

='(')/*如果不是左括号并且栈不为空*/

{

op=pop(&st);/*出栈并存入数组中*/

ch[k++]=op.op;

if(st.size>0)/*再次检查栈是否为空,*/

op=top(&st);

else

break;/*为空就结束*/

}

pop(&st);/*去掉左括号*/

}

if(c=='+'||c=='-')/*如果是+-号*/

{

op.op=c;

op.level=1;/*优先级为1*/

if(st.size==0)

{

push(&st,op);/*如果此时栈为空直接入栈*/

}

else

{

ops=top(&st);/*观察栈顶*/

while(ops.level>=op.level)/*如果栈顶优先级高*/

{

ops=pop(&st);

ch[k++]=ops.op;/*将栈顶元素取出存入数组中*/

if(st.size>0)

ops=top(&st);/*进行判空操作,栈为空结束*/

else

break;

}

push(&st,op);/*此时栈顶优先级低,入栈*/

}

}

if(c=='*'||c=='/'||c=='%')/*如果是*/%号*/

{

op.op=c;

op.level=2;/*优先级为1*/

if(st.size==0)

{

push(&st,op);/*如果此时栈为空直接入栈*/

}

else

{

ops=top(&st);/*观察栈顶*/

while(ops.level>=op.level)/*如果栈顶优先级高*/

{

ops=pop(&st);/*将栈顶元素取出存入数组中*/

ch[k++]=ops.op;

if(st.size>0)

ops=top(&st);/*进行判空操作,栈为空结束*/

else

break;

}

push(&st,op);/*此时栈顶优先级低,入栈*/

}

}

c=str[i++];/*索引自加检索下一个字符*/

}

while(st.size!

=0)/*最后判断栈如果不为空*/

{

ops=pop(&st);/*取出栈内元素存入数组中*/

ch[k++]=ops.op;

}

ch[k]='\0';/*将\0作为结尾存入数组*/

}

 

doubleCalResult(charexp[])/*后缀表达式的计算*/

{

charc;

numstacknumst;/*建立数值栈*/

doubled1,d2,dr;

intk=0;/*后缀表达式的索引*/

inti=0;/*将字符转化为浮点数的索引*/

char*s;

chartrans[100];/*存字符表示的一段数字*/

init2(&numst);/*实现数值栈*/

c=exp[k++];

while(c!

='\0')/*开始扫描后缀表达式*/

{

if(c=='+'||c=='-'||c=='*'||c=='/'||c=='%')/*如果是操作符*/

{

switch(c)

{

case'+':

/*如果是加法操作*/

d2=pop2(&numst);

d1=pop2(&numst);

dr=d1+d2;/*相加后入栈*/

push2(&numst,dr);

break;

case'-':

/*如果是减法操作*/

d2=pop2(&numst);

d1=pop2(&numst);

dr=d1-d2;/*相减后入栈*/

push2(&numst,dr);

break;

case'*':

/*如果是乘法操作*/

d2=pop2(&numst);

d1=pop2(&numst);

dr=d1*d2;/*相乘后入栈*/

push2(&numst,dr);

break;

case'/':

/*如果是除法操作*/

d2=pop2(&numst);

d1=pop2(&numst);

dr=d1/d2;/*相除后入栈*/

push2(&numst,dr);

break;

case'%':

/*如果是取余操作*/

d2=pop2(&numst);

d1=pop2(&numst);

dr=(double)((int)d1%(int)d2);/*类型转化并取余后入栈*/

push2(&numst,dr);

break;

}

}

if(c>='0'&&c<='9'||c=='.')/*如果是字符表示的数字*/

{

while(c>='0'&&c<='9'||c=='.')

{

trans[i++]=c;/*将字符存入数组进行下一个的扫描*/

c=exp[k++];

}

trans[i++]='\0';

i=0;

s=trans;/*将指针指向该数组*/

d1=atof(s);/*利用函数将字符串转化为浮点数*/

push2(&numst,d1);

}

c=exp[k++];

}

returnpop2(&numst);/*最后结果将在数值栈中,取出作为返回值*/

}

下面给出的是用中缀直接计算算法实现的程序的源代码:

#include/*导入需要用到的各种包*/

#include

#include

typedefstruct/*定义结构体用来存储操作符*/

{

charop;/*存储字符*/

intlevel;/*存储优先级*/

}OpNode;

typedefstruct

{

OpNodeop[100];

inttop;

intsize;/*表示栈内元素的个数*/

}stack;/*定义符号栈*/

voidinit(stack*st)/*初始化栈*/

{

st->size=0;

st->top=0;

}

OpNodepop(stack*a)/*出栈*/

{

if(a->size==0)/*如果栈为空结束操作*/

{

exit(-1);

}

a->size--;

returna->op[--(a->top)];/*取出栈顶元素*/

}

voidpush(stack*a,OpNodeop)/*入栈函数*/

{

a->size++;

a->op[(a->top)++]=op;

}

OpNodetop(stack*a)/*观察栈顶函数*/

{

if(a->size==0)/*如果栈为空结束操作*/

{

printf("stackisempty\n");

exit(-1);

}

returna->op[(a->top)-1];/*只得到栈顶的值而不出栈*/

}

 

typedefstruct/*定义数值栈*/

{

doublenum[100];

inttop;/*栈顶指针*/

intsize;

}numstack;

voidinit2(numstack*st)/*初始化数值栈*/

{

st->size=0;

st->top=0;

}

doublepop2(numstack*a)/*数值栈出栈*/

{

if(a->size==0)/*出栈前的判空*/

{

exit(-1);

}

a->size--;

returna->num[--(a->top)];/*得到栈顶的值*/

}

voidpush2(numstack*a,doublenum)/*入栈*/

{

a->size++;

a->num[(a->top)++]=num;

}

voidmain()/*主函数*/

{

doubleDirectcalresult(charstr[]);

charstr[100];/*str存储原算术表达式*/

printf("算术表达式为:

\n");

gets(str);

printf("直接运算的结果为:

%f\n",Directcalresult(str));/*调用直接计算函数*/

inta;

scanf(&a);

}

 

doubleDirectcalresult(charstr[])/*表达式的直接计算出结果*/

{

stackms;/*建立符号栈*/

numstackmns;/*建立数值栈*/

doublecalculate(doubleod1,doubleod2,OpNodeop);

intindex=0;/*str的索引*/

intlen=strlen(str);

charc;

chartrans[100];/*存放数值的一段字符*/

inti=0;/*trans的索引*/

char*s;

doubled;

OpNodetempn;/*存放当前扫描的操作符*/

OpNodetempln;

doubleoda,odb,odr;

doubleresult;/*作为返回值返回结果*/

init(&ms);/*实现两个栈*/

init2(&mns);

while(index

{

c=str[index++];

if((!

isdigit(c))&&(c!

='-')&&(c!

='+')&&(c!

='%')&&(c!

='/')&&(c!

='*')&&(c!

='(')&&(c!

=')')){

printf("输入字符的格式错误\n");

break;

}

if(isdigit(c)||c=='.')/*如果是数字字符或小数点*/

{

while(isdigit(c)||c=='.')

{

trans[i]=c;

trans[i+1]='\0';

i++;/*将其存入数组扫描下一个*/

c=str[index++];

}

//trans[i++]='\0';/*扫描完一个数结束数组*/

i=0;/*索引归0*/

s=trans;

d=atof(s);

push2(&mns,d);/*转化为浮点数入栈*/

}

if(c=='+'||c=='-')/*如果是+-*/

{

tempn.level=1;/*优先级设为1*/

tempn.op=c;

if(ms.size==0)

{

push(&ms,tempn);/*栈为空直接入栈*/

}

else

{

templn=top(&ms);

while(templn.level>=tempn.level)/*栈顶优先级高*/

{

templn=pop(&ms);/*取出操作数和操作符计算*/

odb=pop2(&mns);

oda=pop2(&mns);

odr=calculate(oda,odb,templn);

push2(&mns,odr);/*结算结果入栈*/

if(ms.size>0)

{

templn=top(&ms);/*如果栈空结束*/

}

else

break;

}

push(&ms,tempn);/*操作符入栈*/

}

}

if(c=='*'||c=='/'||c=='%')/*如果是+/%操作*/

{

tempn.level=2;/*定义优先级为2*/

tempn.op=c;

if(ms.size==0)

{

push(&ms,tempn);

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > PPT模板 > 国外设计风格

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1