河北联合大学数据结构报告正文.docx
- 文档编号:23006128
- 上传时间:2023-04-30
- 格式:DOCX
- 页数:22
- 大小:245.54KB
河北联合大学数据结构报告正文.docx
《河北联合大学数据结构报告正文.docx》由会员分享,可在线阅读,更多相关《河北联合大学数据结构报告正文.docx(22页珍藏版)》请在冰豆网上搜索。
河北联合大学数据结构报告正文
一、设计思想
设计目标是用两种算法实现中缀式转后缀式,并计算出表达式的值。
第一种算法是给出一个中缀式,编译运行后输出后缀式,并计算后缀式的值。
首先,先创建两个数组,一个用于存储输入的中缀式,并以“#”结束,一个用于输出后缀式。
创建一个操作符栈,初始化并写好出入栈函数,用操作符栈存储操作符。
对中缀表达式进行遍历时,遇到数值就直接输入要输出后缀表达式的数组,遇到操作符时,首先对操作符的优先级进行设置,“*”,“/”,“%”的优先级设置为最高,“+”“-”的优先级低于前三个符号,“#”的优先级设置为最低。
对操作符栈进行操作时首先将“#”放入栈顶。
判断栈顶操作符与当前操作符优先级的大小,若当前操作符优先级大的话直接入栈,若当前操作符小于或者等于栈顶运算符的话栈顶操作符出栈,并输入后缀式所在的数组,当前操作符再入栈,遇到“(”时,此时认为“(”的优先级为最高,直接入栈,但是当它入栈后优先级变为最小,当栈顶为“(”时操作符可以直接入栈,其他操作符直接入栈直至遇到“)”时,与“(”配对,括号之间的所有操作符全部出栈并输入后缀式。
继续遍历中缀式。
当遍历到“#”时认为遍历中缀式结束。
此时操作符栈所有操作符出栈并输入后缀式,打印后缀式。
得到后缀式后,声明并初始化数值栈,写入入栈出栈函数,对后缀式进行遍历,遇到数值直接入栈,每遇到操作符,从数值栈栈顶取两个数进行计算,将运算结果入数值栈,继续遍历后缀式直至表达式结束,得到的结果就是后缀式的计算值。
第二种算法不将中缀式转换为后缀式,而是直接对中缀式进行操作,开始声明并初始化栈,一个操作符栈,一个数值栈。
直接对中缀式进行遍历,同时也要声明操作符的优先级,“*”,“/”,“%”的优先级设置为2,“+”,“-”的优先级设置为1,然后开始遍历中缀式,遇到字符时首先判断字符类型,也就是sort值,当sort为1时表示读到的是操作符,入操作符栈,当sort为2时读到的是数,入数值栈,遇到数值直接入栈,遇到“(”时,设置其优先级为零,但是直接入栈,不用比较优先级大小,直至遇到“)”时才出操作符栈。
操作符入栈时要进行优先级的比较,若大于栈顶操作符的优先级直接入栈,否则操作符栈的栈顶操作符先出栈,当前操作符再入栈,每当有操作符出栈时,都要从数值栈栈顶出来两个数进行运算,运算结果再压入数值栈中,直至表达式遍历结束。
结束时看数值栈和操作符栈是否为空,不为空的话操作符栈元素出栈,从数值栈顶取两个元素进行计算,计算结果再次压入数栈,如此循环直至操作符栈为空,计算结果压入数值栈中,得到的结果就是中缀表达式的值。
得到的结果就是double类型数据。
调用sprintf函数,此函数用于将各种类型的数据转化为字符串并将其输出。
二、算法流程图
图1为扫描并存储中缀式,遍历中缀式时读到数字或者小数点时直接入要输出后缀式的数组,读到操作符时入操作符栈,入栈前先跟操作符栈顶操作符进行优先级比较,优先级大直接入栈,否则栈顶操作符出栈输入后缀表达式所在数组,当前操作符再入栈,直至读到“#”为止。
图2为计算机后缀表达式,此时遍历后缀表达式,读到数直接入数栈,每读到运算符就从数栈出来两个数进行计算,计算结果压入数栈,直至遍历结束。
计算结果就是表达式的值。
图3为算法二的流程图,不用将中缀表达式转换成后缀表达式,而是直接进行处理,遇到数入数栈,遇到操作符先进行优先级比较,若栈顶运算符优先级大于或者等于当前运算符,栈顶运算符出栈并从数栈取两个数进行计算,计算结果入数栈,当前运算符再入栈。
如此循环直至遍历表达式结束。
图1中缀转后缀算法流程图
图2后缀表达式计算算法流程图
图3直接处理中缀表达式算法流程图
三、源代码
下面给出的是用中缀式转后缀式再计算结果算法实现的程序的源代码:
#include
#defineStackSize100/*定义栈大小为100*/
typedefstruct{/*定义数值栈*/
doublearray[StackSize];/*定义数值类型为双精度浮点数*/
inttop;
}OdNode;/*数值栈名为OdNode*/
typedefcharElemType;
typedefstruct{/*定义操作符栈*/
ElemTypearray[StackSize];
inttop;
}OpNode;/*操作符栈名为OpNode*/
voidOdInit(OdNode*Od){/*初始化数值栈,由指针s指出*/
Od->top=-1;}/*设置栈顶为空*/
intOdpush(OdNode*Od,doublen){/*定义数值栈入栈函数*/
if(Od->top Od->top=Od->top+1;/*若栈不满,则将n进栈*/ Od->array[Od->top]=n;/*栈顶元素变为n*/ return1;} else{/*若栈判断为满,则返回0*/ return0;}} doubleOdpop(OdNode*Od){/*定义数值栈出栈函数*/ doublen; if(-1==Od->top){/*判断栈顶是否为空,若栈顶为空,则返回1*/ return1;} else{ n=Od->array[Od->top];/*若栈顶不为空,则将栈顶元素n出栈*/ (Od->top)--;/*有元素出栈,top自减*/ returnn;}} voidOpInit(OpNode*Op){/*初始化操作符栈*/ Op->top=-1;}/*设置栈顶为空*/ intOppush(OpNode*Op,ElemTypee){/*定义操作符栈入栈函数*/ if(Op->top Op->top=Op->top+1;/*若栈不满,则将e进栈*/ Op->array[Op->top]=e;/*栈顶元素变为e*/ return1;} else{/*若栈判断为满,则返回0*/ return0;}} ElemTypeOppop(OpNode*Op){/*定义操作符栈出栈函数*/ ElemTypen; if(-1==Op->top){/*判断栈顶是否为空,若栈顶为空,则返回1*/ return1;} else{ n=Op->array[Op->top];/*若栈顶不为空,则将栈顶元素n出栈*/ (Op->top)--;/*有元素出栈,top自减*/ returnn;}} intGetTop(OpNodeOp,ElemType*e){/*定义取出栈顶元素的函数*/ if(0==Op.top){/*若栈顶元素为空,则返回0*/ *e=Op.array[Op.top];/*指针e指向栈顶元素*/ return0;} else{/*若栈顶元素不为空,则返回1*/ *e=Op.array[Op.top];/*指针e指向栈顶元素*/ return1;}} intSLevel(intmode,charoper){/*定义比较操作符优先级的函数*/ /*返回操作符oper代表优先级的整数值,mode为1,表示oper是栈顶操作符,否则是当前操作符*/ inttmp;/*定义临时变量*/ switch(oper){ case'#': tmp=0;break;/*定义#优先级为0*/ case'(': tmp=(mode? 1: 6);break;/*若(是栈顶操作符,则优先级为1,否则优先级为6*/ case'+': case'-': tmp=(mode? 3: 2);break;/*若+或-是栈顶操作符,则优先级为3,否则优先级为2*/ case'*': case'/': case'%': tmp=(mode? 5: 4);break;/*若*、/或%是栈顶操作符,则优先级为5,否则优先级为4*/ case')': tmp=(mode? 7: 1);break;/*若)是栈顶操作符,则优先级为7,否则优先级为1*/ } returntmp;}/*返回所得tmp的值*/ charCLevel(charw,charch){/*判定操作符栈的栈顶操作符w与当前操作符ch之间的优先级关系*/ intgrade;/*取得栈顶操作符与当前操作符的优先级*/ grade=SLevel(1,w)-SLevel(0,ch);/*计算取得操作符与当前操作符的差值*/ if(grade>0)/*差值大于0,返回>*/ return'>'; else{ if(grade==0)/*说明取得操作符和当前操作符优先级相等*/ return'='; else/*否则,取得操作符优先级小于当前操作符* return'<';}} voidchange(charE[],charA[]){/*中缀变后缀的实现函数*/ /*E为原前缀式,A为要得到的后缀式*/ OpNodeOp;/*声明一个操作符栈Op*/ inti=0;/*i作为扫描数组E的指针*/ intj=0;/*j用来指示数组A中待写入字符的位置*/ charch=E[i];/*E中第一个字符送给ch*/ charw='\0'; OpInit(&Op);/*初始化操作符栈Op*/ Oppush(&Op,'#');/*先把#压入栈内*/ while(ch! ='#'){/*当ch取得的元素不是#时执行以下命令*/ if(ch>='0'&&ch<='9'||ch=='.'){/*若取得的元素为0到9或者是小数点*/ while(ch>='0'&&ch<='9'||ch=='.'){ A[j]=ch;/*将获得的元素赋予A数组*/ j++;/*A写入位置后移*/ i++;/*E向后扫描*/ ch=E[i];}/*将数组E的下一个元素赋值给ch*/ A[j]=''; j++;}/*给A中的每个数后加一个空格*/ if(ch=='+'||ch=='-'||ch=='*'||ch=='/' ||ch=='%'||ch=='('||ch==')'||ch=='#'){/*若取得的元素为操作符*/ GetTop(Op,&w);/*取Op的栈顶元素*/ while(CLevel(w,ch)=='>'){/*栈顶操作符w比取得的操作符ch的优先级大*/ A[j]=w;/*将w赋予数组A*/ j=j+1; Oppop(&Op);/*将栈顶操作符w出栈*/ GetTop(Op,&w);}/*取得的操作符入栈*/ if(CLevel(w,ch)=='<')/*若栈顶操作符w比取得的操作符ch的优先级小*/ Oppush(&Op,ch);/*取得的操作符直接入栈*/ else{ if(CLevel(w,ch)=='='&&w! ='#'){/*若栈顶操作符w与取得的操作符ch的优先级相等*/ Oppop(&Op);/*将栈顶操作符出栈*/ GetTop(Op,&w);}}}/*观察栈顶操作符*/ if(E[i]! ='#')/*若取得的字符不是#,i加1*/ i++; ch=E[i];}/*将从E数组取出的元素赋予ch*/ while(w! ='#'){/*取得的操作符不是#*/ A[j]=w;/*将操作符赋予A数组*/ j++; Oppop(&Op);/*Op栈顶元素出栈*/ GetTop(Op,&w);} A[j]='#'; A[++j]='\0';} doubleCalc(chararr[]){/*计算后缀表达式的值*/ OdNodeOd;/*声明一个数值栈Od*/ inti=0;/*定义临时变量i*/ charch; doublex=0,d=1.0; OdInit(&Od);/*初始化数值栈*/ ch=arr[i];/*将受到的数组的元素赋值给ch*/ while(ch! ='#'){ switch(ch){/*读取字符串中的数值部分*/ case'0': case'1': case'2': case'3': case'4': case'5': case'6': case'7': case'8': case'9': case'.': while(ch! =''){/*取得的字符不为空*/ if('0'<=ch&&ch<='9'){ while('0'<=ch&&ch<='9'){/*每读到一个整数部分就*10*/ x=x*10+(ch-'0'); i=i+1; ch=arr[i];}} else{if(ch=='.'){ ch=arr[++i]; while('0'<=ch&&ch<='9'){/*每独到一个小数部分就/10*/ d=d*10; x=x+(ch-'0')/d; ch=arr[++i];}}}}break;/*读取数组下一个元素*/ case'+': /*若取得的字符为+,从数值栈取两个元素进行+运算*/ x=Odpop(&Od)+Odpop(&Od);break; case'-': /*若取得的字符为-,从数值栈取两个元素进行-运算*/ x=Odpop(&Od); x=Odpop(&Od)-x;break; case'*': /*若取得的字符为*,从数值栈取两个元素进行*运算*/ x=Odpop(&Od)*Odpop(&Od);break; case'/': /*若取得的字符为/,从数值栈取两个元素进行/运算*/ x=Odpop(&Od); x=Odpop(&Od)/x;break; case'%': /*若取得的字符为%,从数值栈取两个元素进行%运算*/ x=Odpop(&Od); x=(double)((int)Odpop(&Od)%(int)x);break;} Odpush(&Od,x);/*将计算结果x入栈*/ x=0;/*x归零*/ i=i+1; ch=arr[i];/*继续进行*/ d=1.0;}/*d归零*/ returnOdpop(&Od);}/*返回数值栈顶元素,即结果值*/ voidmain(){/*主函数*/ charE[100];/*声明一个长度为100的数组E*/ charA[100];/*声明一个长度为100的数组A*/ printf("Pleaseinputtheinfixexpresswitha'#'inttheend: ");/*输出提示信息*/ gets(E);/*获取E数组中的表达式*/ change(E,A);/*调用中缀式转后缀式函数*/ printf("Thesurffixexpressis: %s\n",A);/*输出后缀式*/ printf("Theresultis: %f\n",Calc(A));/*调用计算后缀式的函数,并将结果输出*/ getchar();} 下面给出的是用中缀表达式直接进行入栈计算算法实现的程序的源代码: #include #include #include typedefstruct{/*声明操作符结构体*/ charop;/*声明操作符类型*/ charlevel;/*声明操作符优先级*/ }opNode; typedefunion{ opNodeopNode;/*声明操作符*/ doublevalue;/*声明value数值为double型*/ }Node; typedefstruct{/*声明栈的结构体*/ charleixing;/*声明一个字符型sort*/ Node*a[100];/*指定数组大小为100*/ inttop;/*声明栈顶*/ }Stack; Stack*init_sta(){/*初始化栈*/ inti; Stack*s=(Stack*)malloc(sizeof(Stack));/*分配一个类型为Stack的 结点变量的空间,空间大小为sizeof(Stack),并将首地址放入指针变量s中*/ s->top=0; for(i=0;i<100;i++)/*遍历栈,全为空则栈空*/ s->a[i]=NULL; returns;} char*substr(char*s,intn1,intn2){/*截取子串函数*/ char*ss=(char*)malloc(sizeof(char)*(n2-n1+2));/*分配空间,大小为 n2-n1+2,并将首地址放入指针变量ss中*/ inti,j=0; for(i=n1;i ss[j++]=s[i];} ss[j]='\0';/*字符串后面加上'0'*/ returnss;} intempty(Stack*ss){/*判断栈空函数*/ returnss->top;}/*返回栈顶元素*/ Node*Top(Stack*ss){/*观察栈顶函数*/ if(ss->top<=0){/*若栈顶为空,则返回0*/ return0;} else{/*若栈顶不为空,则返回栈顶元素*/ returnss->a[ss->top-1];}} Node*Pop(Stack*ss){/*出栈函数*/ if(ss->top<=0){/*栈顶为空,返回0*/ return0;} else{/*否则,栈顶元素出栈*/ ss->top--; returnss->a[ss->top];}} voidPush(Stack*p,Node*n){/*进栈函数*/ Node*temp=(Node*)malloc(sizeof(Node));/*分配空间,空间大小为 sizeof(Node),并将首地址放入指针变量temp中*/ if(p->top>=100){/*判断栈是否已满*/ printf("Error! TheStackisfull! \n");/*输出提示信息*/ free(temp);} else{ if(p->leixing==1){/*sort为1,指向的为操作符栈,表明temp为操作符*/ temp->opNode.level=n->opNode.level; temp->opNode.op=n->opNode.op;} else/*sort为2指向的是数值栈,表明temp为数值*/ temp->value=n->value; p->a[p->top]=temp; p->top=p->top+1;}} doublecalc(charop,doublem,doublen){/*每出栈一个操作符,就进行一次运算*/ switch(op){ case'+': returnn+m; case'-': returnn-m; case'*': returnn*m; case'/': returnn/m; case'%': return(int)n%(int)m;}/*计算结束后,返回计算结果*/ return0;} voidmath(char*exp){/*处理函数*/ Node*top;/*声明栈顶*/ Node*temp=(Node*)malloc(sizeof(Node));/*分配空间,并将首地址放入指针变量temp中*/ Node*tempn=(Node*)malloc(sizeof(Node));/*分配空间,并将首地址放入指针变量tempn中*/ Node*tempm;/*声明一个tempm结点指针*/ charc; char*temps=""; unsignedintindex=0,tempindex;/*声明一个索引和一个临时索引*/ doublea,b; Stack*s1=init_sta();/*初始化栈s1*/ Stack*s2=init_sta();/*初始化栈s2*/ s1->leixing=2;/*s1的类型为2,栈为数值栈*/ s2->leixing=1;/*s2的类型为1,栈为操作符栈*/ while(index c=exp[index]; if(c>='0'&&c<='9'||c=='.'){/*读取表达式中的各个数值*/ tempindex=index+1; while(tempindex tempindex++;}/*当一个数没有读完,索引后移,直至整个数读完*/ if(tempindex==strlen(exp)-1){/*当临时索引到达表达式尾部时,直接截取*/ temps=substr(exp,index,index+1);} else{ temps=substr(exp,index,tempindex);} index=tempindex;/*索引指向临时索引所在位置*/ temp->value=atof(temps);/*将截取的子串转化为double类型*/ Push(s1,temp);}/*将转化后的数压入数值栈*/ if(c=='+'||c=='-'){/*字符为+或-时*/ tempn->opNode.op=c; tempn->opNode.level=1;/*设置优先级为1*/ top=Top(s2); while(empty(s2)>0&&tempn->opNode.level<=top->opNode.level){/*操作符栈不为空, 并且栈顶操作符优先级高于或者等于当前操作符*/ tempm=Pop(s2);/*操作符栈顶操作符出栈*/ a=Pop(s1)->value;/*数值栈顶出来两个数*/ b=Pop(s1)->value; temp->value=calc(tempm->opNode.op,a,b);/*两个数进行运算*/ Push(s1,temp);/*运算结果压入数值栈*/ top=Top(s2);} Push(s2,tempn); index++;} if(c=='*'||c=='/'||c=='%'){/*字符为*或/或%时*/ tempn->opNode.op=c;/*临时操作符指向c*/ tempn->opNode.level=2;
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 河北 联合 大学 数据结构 报告 正文
![提示](https://static.bdocx.com/images/bang_tan.gif)