數(shù)據(jù)結(jié)構(gòu)實(shí)驗(yàn)報告_第1頁
數(shù)據(jù)結(jié)構(gòu)實(shí)驗(yàn)報告_第2頁
數(shù)據(jù)結(jié)構(gòu)實(shí)驗(yàn)報告_第3頁
數(shù)據(jù)結(jié)構(gòu)實(shí)驗(yàn)報告_第4頁
數(shù)據(jù)結(jié)構(gòu)實(shí)驗(yàn)報告_第5頁
已閱讀5頁,還剩8頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

..課程設(shè)計實(shí)驗(yàn)報告實(shí)驗(yàn)名稱:表達(dá)式類型的實(shí)現(xiàn)編譯環(huán)境:硬件:PC軟件:VS2010問題描述一個表達(dá)式和一棵二叉樹之間,存在著自然的對應(yīng)關(guān)系。寫一個程序,實(shí)現(xiàn)基于二叉樹表示的算術(shù)表達(dá)式Expression的操作。基本要求假設(shè)算術(shù)表達(dá)式Expression可以含有變量〔a~z、常量〔0~9和二元運(yùn)算符〔+,-,*,/,^〔乘冪。實(shí)現(xiàn)以下操作。ReadExpr<E>——以字符序列的形式輸入語法正確的前綴表示式并構(gòu)造表達(dá)式E。WriteExpr<E>——用帶括弧的前綴表示式輸出表達(dá)式E。Assign<V,c>——實(shí)現(xiàn)對變量V的賦值<V=c>,變量的初值為0。Value<E>——對算術(shù)表達(dá)式E求值。CompoundExpr<P,E1,E2>——構(gòu)造一個新的復(fù)合表達(dá)式<E1>P<E2>。選作內(nèi)容:增加常數(shù)合并操作MergeConst<E>-------合并表達(dá)式中E的所有常數(shù)運(yùn)算。例如:表達(dá)式E=2+2*1-A進(jìn)行合并常數(shù)的操作后,求得E=4-A〔2以表達(dá)式的原書寫形式輸入需求分析1.以字符序列的形式輸入語法正確的中綴表示式并構(gòu)造表達(dá)式E。即要根據(jù)正確的前綴式建立一棵二叉樹T。2.用帶括弧的前綴表達(dá)式輸出表達(dá)式E。即要求在前綴遍歷二叉樹的時候考慮運(yùn)算符的優(yōu)先級,在適當(dāng)?shù)奈恢幂敵隼ɑ ?.實(shí)現(xiàn)對變量V的賦值〔V=c,變量的初值為0。那就在中綴遍歷二叉樹的過程中比較結(jié)點(diǎn)的值是否為V,找到V以后將c賦給V。4.對算術(shù)表達(dá)式E求值。如果表達(dá)式中有變量的話,首先提示用戶表達(dá)式中變量,建議先執(zhí)行操作3〔實(shí)現(xiàn)對變量V賦值,執(zhí)行完后再回來執(zhí)行表達(dá)式求值這一步驟。表達(dá)式求值利用遞歸,如果某個結(jié)點(diǎn)的值為運(yùn)算符并且它的左右孩子結(jié)點(diǎn)的值為數(shù)據(jù),那么就把〔左孩子〔運(yùn)算符〔右孩子的結(jié)果賦給該結(jié)點(diǎn)。一層一層往上,最后只剩下一個根結(jié)點(diǎn)。此時根結(jié)點(diǎn)的值就是表達(dá)式E的值。5.構(gòu)造一個新的復(fù)合表達(dá)式〔E1P〔E2。只要先構(gòu)造表達(dá)式E1的二叉樹和E2的二叉樹,然后利用P把這兩棵二叉樹連接起來構(gòu)成一棵新的二叉樹。6.合并表達(dá)式E中所有常數(shù)運(yùn)算。此原理類似于對表達(dá)式E求值,不同之處只在于該功能只對常數(shù)合并。概要設(shè)計1.樹的抽象數(shù)據(jù)類型定義:ADTTree{數(shù)據(jù)對象D:D是具有相同特性的數(shù)據(jù)元素的集合。數(shù)據(jù)關(guān)系R:若D為空集,則稱為空樹;若D僅含一個數(shù)據(jù)元素,則R為空集,否則R={H},H是如下二元關(guān)系:在D中存在唯一的稱為根的數(shù)據(jù)元素root,它在關(guān)系H下無前驅(qū);若D-{root}≠ф,則存在D-{root}的一個劃分D1,D2,…Dm<m>0>,對任意j≠k<1<=j,k<=m>有Dj∩Dk=ф,且對任意的i<1≤i≤m>,唯一存在數(shù)據(jù)元素Xi∈Di,有<root,Xi>∈H;對應(yīng)于D-{root}≠ф的劃分,H-{<root,Xi>…<root,Xm>}有唯一的一個劃分H1,H2…Hm<m>0>,對任意j≠k<1<=j,k<=m>有Dj∩Dk=ф,且對任意的i<1≤i≤m>,Hi是Di上的二元關(guān)系,<Di,{Hi}>是一棵符合本定義的樹,稱為根的root的子樹?;静僮?DoubleExpression<char*exp>;功能:算術(shù)表達(dá)式求值doublecalculate<doubleopnd1,charop,doubleopnd2>;功能:操作數(shù)四則運(yùn)算voidpush<char,char,double,ExpressionCalculateStack*>;功能:入棧doublepop<char,ExpressionCalculateStack*>;功能:出棧voidGetNextNotation<char*notation,char*exp>;功能:讀下一個運(yùn)算符或操作數(shù)charGetTypeOfNotation<char*notation>;功能:判定是運(yùn)算符或是操作數(shù)intCompareOpPrior<charop2,charop1>;功能:運(yùn)算符優(yōu)先級別比較BTNode*ReadExpr<chars[],inti,intj>功能:讀入表達(dá)式voidWriteExpr<BTNode*b>功能:/把輸入的表達(dá)式轉(zhuǎn)換為相應(yīng)的二叉樹,并以前綴表達(dá)式的形式輸出charSeek<chars[],intk>功能:判斷是否有字母輸入voidCompoundExpr<charE1[],charE2[],charp>功能:復(fù)合表達(dá)式voidAssign<chars[],chari,charj>功能:對變量進(jìn)行復(fù)制}流程圖:MMian函數(shù)對算術(shù)表達(dá)式求值查找式中的變量Seek以中綴方式輸入表達(dá)式ReadExpr以前綴方式輸出表達(dá)式WriteExpr對式中的變量進(jìn)行復(fù)制Assign3菜單65412復(fù)合表達(dá)式對變量賦值,即執(zhí)行步驟3NY是否有變量對算術(shù)表達(dá)式求值查找式中的變量Seek以中綴方式輸入表達(dá)式ReadExpr以前綴方式輸出表達(dá)式WriteExpr對式中的變量進(jìn)行復(fù)制Assign3菜單65412復(fù)合表達(dá)式對變量賦值,即執(zhí)行步驟3NY是否有變量常數(shù)合并常數(shù)合并程序清單:頭文件〔MyExpression.h#include<stdio.h>#include<malloc.h>#include<string.h>#include<math.h>#include<conio.h>#defineMaxSize100typedefcharElemType;typedefstructnode{ElemTypedata;structnode*lchild;structnode*rchild;}BTNode;#defineMAX_EXP_LEN128/*表達(dá)式最大長度*/#defineMAX_NOTATION_NUM32/*一個表達(dá)式中的最大算符個數(shù)*/#defineMAX_NOTATION_LEN20/*表達(dá)式中一個算符的最大字串長度*/#defineNULL0typedefstructstack{/*表達(dá)式計算堆棧*/doubleOpdStack[MAX_NOTATION_NUM];/*操作數(shù)堆棧*/charOpStack[MAX_NOTATION_NUM];/*運(yùn)算符堆棧*/intOpdStackTop,/*操作數(shù)堆棧頂指針*/OpStackTop;/*運(yùn)算符堆棧頂指針*/}ExpressionCalculateStack;#defineOPND'D'/*操作數(shù)類型標(biāo)志*/#defineOPTR'R'/*運(yùn)算符類型標(biāo)志*/#defineCONTINUE_READ_NEXT_NOTATION'C'/*表達(dá)式掃描標(biāo)志,繼續(xù)掃描*/#defineSTOP_READ_NEXT_NOTATION'S'/*表達(dá)式掃描標(biāo)志,暫停掃描*//*部分子函數(shù)聲明如下〔主要是表達(dá)式求值函數(shù)*/doubleExpression<char*exp>;/*算術(shù)表達(dá)式求值*/doublecalculate<doubleopnd1,charop,doubleopnd2>;/*操作數(shù)四則運(yùn)算*/voidpush<char,char,double,ExpressionCalculateStack*>;/*入棧*/doublepop<char,ExpressionCalculateStack*>;/*出棧*/voidGetNextNotation<char*notation,char*exp>;/*讀下一個運(yùn)算符或操作數(shù)*/charGetTypeOfNotation<char*notation>;/*判定是運(yùn)算符或是操作數(shù)*/intCompareOpPrior<charop2,charop1>;/*運(yùn)算符優(yōu)先級別比較*/源代碼文件〔MyExpression.c#include"MyExpression.h"#include"stdlib.h"externdoubleExpression<char*oldexp>;externintCompareOpPrior<charop2,charop1>;externcharGetTypeOfNotation<char*notation>;externvoidGetNextNotation<char*notation,char*exp>;externdoublecalculate<doubleopnd1,charop,doubleopnd2>;externdoublepop<chartype,ExpressionCalculateStack*s>;externvoidpush<chartype,charop,doubleopnd,ExpressionCalculateStack*s>;BTNode*ReadExpr<chars[],inti,intj>{BTNode*p;intk,plus=0,posi;if<i==j>{p=<BTNode*>malloc<sizeof<BTNode>>;p->data=s[i];p->lchild=NULL;p->rchild=NULL;returnp;}//以下是i!=j的情況if<i!=j>{for<k=i;k<=j;k++> {if<s[k]=='+'||s[k]=='-'> { plus++; posi=k; }}if<plus==0>{ for<k=i;k<=j;k++> if<s[k]=='*'||s[k]=='/'> { plus++; posi=k; }} p=<BTNode*>malloc<sizeof<BTNode>>; p->data=s[posi]; p->lchild=ReadExpr<s,i,posi-1>; p->rchild=ReadExpr<s,posi+1,j>; returnp; // }}}voidWriteExpr<BTNode*b>//把輸入的表達(dá)式轉(zhuǎn)換為相應(yīng)的二叉樹,并以前綴表達(dá)式的形式輸出{ if<b!=NULL> { printf<"%c",b->data>; if<b->lchild!=NULL||b->rchild!=NULL> { printf<"<">; WriteExpr<b->lchild>; if<b->rchild!=NULL> printf<",">; WriteExpr<b->rchild>; printf<">">; } }}charSeek<chars[],intk>//判斷是否有字母輸入{chara[1]={0};inti;for<i=0;i<=k;i++> if<s[i]>='A'&&s[i]<='Z'||s[i]>='a'&&s[i]<='z'> returna[0]='1';}voidAssign<chars[],chari,charj>{for<intp=0;p<=strlen<s>-1;p++> if<s[p]==i> s[p]=j;}voidCompoundExpr<charE1[],charE2[],charp>//復(fù)合表達(dá)式{charNewE[MaxSize],q[1];intk=0,i;BTNode*bt1,*bt2,*T;if<p=='+'||p=='-'>//復(fù)合函數(shù)為+或-是應(yīng)怎樣復(fù)合{for<i=0;i<strlen<E1>;i++> NewE[i]=E1[i]; NewE[strlen<E1>]=p; for<k=0;k<strlen<E2>;i++,k++> NewE[i+1]=E2[k]; NewE[i+1]='\0'; printf<"復(fù)合后的表達(dá)式為:%s\n\n",NewE>;printf<"其對應(yīng)的二叉樹為:">; T=ReadExpr<NewE ,0,strlen<NewE>-1>; WriteExpr<T>; printf<"\n">;}else{printf<"復(fù)合的表達(dá)式為:">;//復(fù)合符號為*或/是應(yīng)該怎樣復(fù)合這兩個表達(dá)式bt1=ReadExpr<E1,0,strlen<E1>-1>;printf<"<">;WriteExpr<bt1>;printf<">">;printf<"%c",p>;bt2=ReadExpr<E2,0,strlen<E2>-1>;printf<"<">;WriteExpr<bt2>;printf<">">;printf<"\n">;}}voidConbination<chars[],intk>//對常數(shù)項(xiàng)進(jìn)行合并{//intFX=0;if<s[k]=='*'>{if<<s[k-1]>='0'&&s[k-1]<='9'>&&<s[k+1]>='0'&&s[k+1]<='9'>>//判斷是否為數(shù)字{/*FX=s[k-1]*s[k+1];s[k-1]=FX;*/ s[k-1]=<s[k-1]-48>*<s[k+1]-48>+48;for<inti=k;i<strlen<s>;i++> s[i]=s[i+2];}}if<s[k]=='/'>{if<<s[k-1]>='0'&&s[k-1]<='9'>&&<s[k+1]>='0'&&s[k+1]<='9'>>{s[k-1]=<s[k-1]-48>/<s[k+1]-48>+48;for<inti=k;i<strlen<s>;i++> s[i]=s[i+2];}}if<s[k]=='+'>{if<<s[k-1]>='0'&&s[k-1]<='9'>&&<s[k+1]>='0'&&s[k+1]<='9'>>{s[k-1]=<s[k-1]-48>+<s[k+1]-48>+48;for<inti=k;i<strlen<s>;i++> s[i]=s[i+2];}}if<s[k]=='-'>{if<<s[k-1]>='0'&&s[k-1]<='9'>&&<s[k+1]>='0'&&s[k+1]<='9'>>{s[k-1]=<s[k-1]-48>-<s[k+1]-48>+48;for<inti=k;i<strlen<s>;i++> s[i]=s[i+2];}}printf<"常數(shù)合并后為:%s",s>; }voidMergeConst<chars[]>//常數(shù)合并{inti,j,n;for<i=0;i<strlen<s>;i++>{if<s[i]=='*'||s[i]=='/'> Conbination<s,i>;}for<j=0;j<strlen<s>;j++>{if<s[j]=='+'||s[j]=='-'> Conbination<s,j>;}}voidmain<>{doublefx=0;BTNode*b;inti=0,j=0;chars[MaxSize],yesORno,value,getvalue,GetDigitl=NULL,p,E1[7],E2[3],e1,e2;printf<"\n\n表達(dá)式類型實(shí)現(xiàn)的使用說明:\n\n">;printf<"表達(dá)式暫時還不能進(jìn)行括號操作,請不要輸入括號,\n\n">;printf<"數(shù)字的輸入只能是一位數(shù)〔0-9,字母的輸入a-z或A-Z\n\n">;printf<"表達(dá)式輸入時請按以下形式輸入:A-S+D\n\n">;printf<"************************************\n\n">;printf<"1.輸入表達(dá)式2.輸出表達(dá)式\n\n">;printf<"3.對變量賦值4.對表達(dá)式求值\n\n">;printf<"5.復(fù)合表達(dá)式6.常數(shù)合并\n\n">;printf<"7.返回\n\n">;printf<"************************************\n\n">;printf<"請輸入選擇〔1-7">;while<<GetDigitl=getchar<>>!='7'>{switch<GetDigitl> {case'1':{printf<"\n\n請以中綴表達(dá)式形式輸入表達(dá)式,例如a+b*c/d\n\n">;printf<"你的輸入">;getchar<>;gets<s>;//以中綴表達(dá)式形式輸入表達(dá)式printf<"\n">;printf<"你輸入的表達(dá)式為:%s\n",s>;b=ReadExpr<s,0,strlen<s>-1>; printf<"\n請輸入選擇〔1-7\n">; break; } case'2': { printf<"\n對應(yīng)的二叉樹:">; WriteExpr<b>; printf<"\n\n">; printf<"\n請輸入選擇〔1-7\n">; break; } case'3': {while<<yesORno=Seek<s,strlen<s>-1>>=='1'> { printf<"表示式中有變量!\n">; getchar<>;printf<"需要賦值的變量:">; value=getchar<>; getchar<>; printf<"變量值:">; getvalue=getchar<>; Assign<s,value,getvalue>; } b=ReadExpr<s,0,strlen<s>-1>; printf<"\n對應(yīng)的二叉樹:">;WriteExpr<b>;printf<"\n請輸入選擇〔1-7\n">; break; } case'4': {yesORno=Seek<s,strlen<s>-1>; if<yesORno=='1'> printf<"表達(dá)式中有未知變量,請選擇3進(jìn)行變量賦值\n">; else { fx=Expression<s>;/*表達(dá)式求值*/printf<"\n表達(dá)式的運(yùn)算結(jié)果為:%f\n",fx>; } printf<"\n請輸入選擇〔1-7\n">; break; } case'5': { printf<"請從〔+、-、*、/中選擇一個作為復(fù)合符號\n">; printf<"你的選擇是:">; getchar<>; p=getchar<>; printf<"\n">; printf<"請輸入要復(fù)合的第一個表達(dá)式:">; getchar<>; gets<E1>; printf<"\n">; printf<"請輸入要復(fù)合的第二個表達(dá)式:">; gets<E2>; printf<"\n">; CompoundExpr<E1,E2,p>;printf<"\n請輸入選擇〔1-7\n">; break; } case'6': {MergeConst<s>; printf<"\n請輸入選擇〔1-7\n">; break; }} }}//一下是表達(dá)式求值函數(shù)#include"MyExpression.h"doubleExpression<char*oldexp>//表達(dá)式計算函數(shù),輸入的是表達(dá)式字符串{charnotation[MAX_NOTATION_LEN],//存放當(dāng)前符號掃描讀入的符號op1,op2,exp[MAX_EXP_LEN];//存放當(dāng)前操作表達(dá)式charflag=CONTINUE_READ_NEXT_NOTATION;//判別是否繼續(xù)掃描下去intprior;//存放算符優(yōu)先級別比較結(jié)果:op2<op1:-1op2>op1:1//op2=op1:0doubleopnd1,opnd2;//存放當(dāng)前用于計算的2個操作數(shù)ExpressionCalculateStacks;//定義堆棧ss.OpdStackTop=s.OpStackTop=0;strcpy<exp,oldexp>;//把原表達(dá)式復(fù)制給當(dāng)前操作表達(dá)式strcat<exp,"#">;//把‘#’接到exp后面,原exp最后面的‘\0’被取消push<OPTR,'#',0.0,&s>;//初始化表達(dá)式計算堆棧while<1>{if<flag==CONTINUE_READ_NEXT_NOTATION>GetNextNotation<notation,exp>;else/*有運(yùn)算結(jié)果進(jìn)操作數(shù)棧后*/flag=CONTINUE_READ_NEXT_NOTATION;if<GetTypeOfNotation<notation>==OPND>{opnd2=atof<notation>;push<OPND,NULL,opnd2,&s>;//操作數(shù)處理}else//運(yùn)算符處理{op2=notation[0];op1=<char>pop<OPTR,&s>;//運(yùn)算符出棧prior=CompareOpPrior<op2,op1>;if<prior<0>//op2<op1{push<OPTR,op1,0.0,&s>;//剛出棧的運(yùn)算符再次進(jìn)棧push<OPTR,op2,0.0,&s>;//當(dāng)前運(yùn)算符優(yōu)先級別高,進(jìn)棧}if<prior>0>//op2>op2{opnd2=pop<OPND,&s>;opnd1=pop<OPND,&s>;opnd2=calculate<opnd1,op1,opnd2>;push<OPND,NULL,opnd2,&s>;flag=STOP_READ_NEXT_NOTATION;///暫停讀入下一個表達(dá)式符號//使當(dāng)前運(yùn)算符與棧頂運(yùn)算符再作一次比較}if<prior==0>//op2=op1的情況處理{if<op2=='#'>returnpop<OPND,&s>;//結(jié)束運(yùn)算,將運(yùn)算結(jié)果從堆棧中彈出}}}}voidpush<chartype,charop,doubleopnd,ExpressionCalculateStack*s>{if<type==OPND>s->OpdStack[s->OpdStackTop++]=opnd;elses->OpStack[s->OpStackTop++]=op;}doublepop<chartype,ExpressionCalculateStack*s>{if<type==OPND>//是操作數(shù)棧returns->OpdStack[--s->OpdStackTop];else//是運(yùn)算符棧return<double><s->OpStack[--s->OpStackTop]>;}doublecalculate<doubleopnd1,charop,doubleopnd2>{switch<op>{case'+':returnopnd1+opnd2;case'-':returnopnd1-opnd2;case'*':returnopnd1*opnd2;case'/':if<opnd2!=0.0>returnopnd1/opnd2;elsereturn0.0;}return0.0;}voidGetNextNotation<char*notation,char*exp>//讀入下一個完整的符號:操作數(shù)或運(yùn)算符{//把一個完整的操作數(shù)或運(yùn)算符保存到notation[]staticinti=0;//變量i為表達(dá)式掃描的當(dāng)前位置,注意其類型intj;chartype,lasttype=GetTypeOfNotation<exp+i>;for<j=0;exp[i]!='\0';j++,i++>{if<exp[i]==''>continue;notation[j]=exp[i];type=GetTypeOfNotation<notation+j>;if<type==OPTR&&lasttype==OPTR>{i++,j++;break;}//第一次讀到的就是//運(yùn)算符if<type==OPTR&&lasttype==OPND>break;//由讀到的不是運(yùn)算符轉(zhuǎn)為讀到的是運(yùn)算符lasttype=type;}notation[j]=NULL;if<notation[0]=='#'>i=0;//表達(dá)式掃描完畢}charGetTypeOfNotation<char*notation>//判斷一個字符是不是運(yùn)算符{charopstr[]="+-*/<>#";//運(yùn)算符集inti;if<notation[0]=='\0'>returnNULL;for<i=0;opstr[i]!='\0';i++>if<notation[0]==opstr[i]>returnOPTR;//'R'即是運(yùn)算符returnOPND;//'D'即是操作數(shù)或小數(shù)點(diǎn)或其它如空格等}intCompareOpPrior<charop2,charop1>//2個先后出現(xiàn)的運(yùn)算符優(yōu)先級別比較:按P53表3.1//定{charopstr[]="+-*/<>#";inti,j;intpriortable[7][7]=//+-*/<>#{1,1,-1,-1,-1,1,1,1,1,-1,-1,-1,1,1,1,1,1,1,-1,1,1,1,1,1,1,-1,1,1,-1,-1,-1,-1,-1,0,'I',1,1,1,1,'I',1,1,-1,-1,-1,-1,-1,'I',0,};for<i=0;opstr[i]!='\0';i++>i

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論