河北联合大学表达式遍历.docx
《河北联合大学表达式遍历.docx》由会员分享,可在线阅读,更多相关《河北联合大学表达式遍历.docx(26页珍藏版)》请在冰豆网上搜索。
河北联合大学表达式遍历
数据结构(双语)
——项目文档报告
用两种方式实现表达式自动计算
专业:
计算机科学与技术
班级:
指导教师:
姓名:
学号:
目录
一、设计思想……………………………………………………….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);