日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

数据结构—— 基于二叉树的算术表达式求值

發(fā)布時(shí)間:2023/12/4 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构—— 基于二叉树的算术表达式求值 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

實(shí)驗(yàn)五 基于二叉樹(shù)的算術(shù)表達(dá)式求值

數(shù)據(jù)結(jié)構(gòu)——中序表達(dá)式求值(棧實(shí)現(xiàn))
實(shí)驗(yàn)?zāi)康?#xff1a;
1.掌握二叉樹(shù)的二叉鏈表存儲(chǔ)表示和二叉樹(shù)的遍歷等基本算法。
2.掌握根據(jù)中綴表達(dá)式創(chuàng)建表達(dá)式樹(shù)的算法
3.掌握基于表達(dá)式樹(shù)的表達(dá)式求值算法。
實(shí)驗(yàn)內(nèi)容:
問(wèn)題描述
輸入一個(gè)表達(dá)式(表達(dá)式中的數(shù)均為小于10的正整數(shù)),利用二叉樹(shù)來(lái)表示該表達(dá)式,創(chuàng)建表達(dá)式樹(shù),然后利用二叉樹(shù)的遍歷操作求表達(dá)式的值。
輸入要求:
多組數(shù)據(jù),每組數(shù)據(jù)一行,對(duì)應(yīng)一個(gè)算術(shù)表達(dá)式,每個(gè)表達(dá)式均以“=”結(jié)尾。當(dāng)表達(dá)式只有一個(gè)“=”時(shí),輸入結(jié)束。
輸出要求
每組數(shù)據(jù)輸出1行,為表達(dá)式的值。

輸出樣例
15
3
【實(shí)驗(yàn)提示】
首先,讀入表達(dá)式,參照算法6.4創(chuàng)建一個(gè)基于二叉鏈表表示的表達(dá)式樹(shù);然后,對(duì)表達(dá)式樹(shù)進(jìn)行后序遍歷,得到表達(dá)式的值。
【擴(kuò)展提示】
對(duì)于任意一個(gè)算術(shù)表達(dá)式,都可用二叉樹(shù)來(lái)表示。表達(dá)式對(duì)應(yīng)的二叉樹(shù)創(chuàng)建后,利用二叉樹(shù)的遍歷等操作,很容易實(shí)現(xiàn)表達(dá)式的求值運(yùn)算。因此問(wèn)題的關(guān)鍵就是如何創(chuàng)建表達(dá)式樹(shù),下面討論由中綴表達(dá)式創(chuàng)建表達(dá)式樹(shù)的方法。
假設(shè)運(yùn)算符均為雙目運(yùn)算符,則表達(dá)式對(duì)應(yīng)的表達(dá)式樹(shù)中葉子結(jié)點(diǎn)均為操作數(shù),分支結(jié)點(diǎn)均為運(yùn)算符。由于創(chuàng)建的表達(dá)式樹(shù)需要準(zhǔn)確的表達(dá)運(yùn)算次序,因此在掃描表達(dá)式創(chuàng)建表達(dá)式樹(shù)的過(guò)程中,當(dāng)遇到運(yùn)算符時(shí)不能直接創(chuàng)建結(jié)點(diǎn),而應(yīng)將其與前面的運(yùn)算符進(jìn)行優(yōu)先級(jí)比較,根據(jù)比較的結(jié)果再進(jìn)行處理。這種處理方式類(lèi)似于第4章的表達(dá)式求值算法中的運(yùn)算符的比較,可以借助一個(gè)運(yùn)算符棧,來(lái)暫存已經(jīng)掃描到的還未處理的運(yùn)算符。
根據(jù)表達(dá)式樹(shù)與表達(dá)式對(duì)應(yīng)關(guān)系的遞歸定義,每?jī)蓚€(gè)操作數(shù)和一個(gè)運(yùn)算符就可以建立一棵表達(dá)式二叉樹(shù),而該二叉樹(shù)又可以作為另一個(gè)運(yùn)算符結(jié)點(diǎn)的一棵子樹(shù)。可以另外借助一個(gè)表達(dá)式樹(shù)棧,來(lái)暫存已建立好的表達(dá)式樹(shù)的根結(jié)點(diǎn),以便其作為另一個(gè)運(yùn)算符結(jié)點(diǎn)的子樹(shù)而被引用。

為實(shí)現(xiàn)表達(dá)式樹(shù)的創(chuàng)建算法

可以使用兩個(gè)工作棧,一個(gè)稱做OPTR,用以暫存運(yùn)算符;另一個(gè)稱做EXPT,用以暫存已建立好的表達(dá)式樹(shù)的根結(jié)點(diǎn)。
為了便于實(shí)現(xiàn),假設(shè)每個(gè)表達(dá)式均以”#”開(kāi)始,以”#”結(jié)束。
表達(dá)式樹(shù)的創(chuàng)建算法步驟
① 初始化OPTR棧和EXPT棧,將表達(dá)式起始符“#”壓入OPTR棧。
②掃描表達(dá)式,讀入第一個(gè)字符ch,如果表達(dá)式?jīng)]有掃描完畢至“#”或OPTR的棧頂元素不為“#”時(shí),則循環(huán)執(zhí)行以下操作:
i)若ch不是運(yùn)算符,則以ch為根創(chuàng)建一棵只有根結(jié)點(diǎn)的二叉樹(shù),且將該樹(shù)根結(jié)點(diǎn)壓入EXPT棧,讀入下一字符ch;
ii)若ch是運(yùn)算符,則根據(jù)OPTR的棧頂元素和ch的優(yōu)先級(jí)比較結(jié)果,做不同的處理:
若是小于,則ch壓入OPTR棧,讀入下一字符ch;
若是大于,則彈出OPTR棧頂?shù)倪\(yùn)算符,從EXPT棧彈出兩個(gè)表達(dá)式子樹(shù)的根
結(jié)點(diǎn),以該運(yùn)算符為根結(jié)點(diǎn),以EXPT找中彈出的第二個(gè)子樹(shù)作為左子樹(shù),以
EXPT中彈出的第一個(gè)子樹(shù)作為右子樹(shù),創(chuàng)建一棵新二叉樹(shù),并將該樹(shù)根結(jié)點(diǎn)壓入EXPT棧;

若是等于,則OPTR的棧頂元素是“(”且ch是“)”,這時(shí)彈出OPTR 棧頂?shù)摹?#xff08;”,相當(dāng)于括號(hào)匹配成功,然后讀入下一字符ch。

void EvaluateExpression(BiTree &root,char *str) {SqStack OPTR;InitStack(&OPTR);SqStack_BiTree EXPT; SqStack_BiTree_InitStack(EXPT);char ch,x,theta;BiTree a,b;int i=0;Push(&OPTR, '='); //=是表達(dá)式結(jié)束符ch =str[i++];GetTop(&OPTR, &x);while(ch != '=' || x != '='){if(In(ch)) //是7種運(yùn)算符之一{switch(Precede(x, ch)){case '<': //當(dāng)前已經(jīng)壓棧一個(gè)運(yùn)算符(x)比后一個(gè)運(yùn)算符(c)低時(shí),就將c壓棧Push(&OPTR, ch);ch =str[i++];break;case '='://消除小括號(hào) Pop(&OPTR, &x); //脫括號(hào)并接收下一字符 ch =str[i++]; break;case '>':Pop(&OPTR,&theta);BiTree TEMP;TEMP=(BiNode*)malloc(sizeof(BiNode));if(!TEMP)exit(-1);TEMP->data=theta; SqStack_BiTree_Pop(EXPT,b);SqStack_BiTree_Pop(EXPT,a);TEMP->lchild=a;TEMP->rchild=b;SqStack_BiTree_Push(EXPT,TEMP);root=TEMP;break;}}if(ch>='0'&&ch<='9'){BiTree Temp;Temp=(BiNode*)malloc(sizeof(BiNode));if(!Temp)exit(-1);Temp->data=ch;Temp->lchild=NULL;Temp->rchild=NULL;SqStack_BiTree_Push(EXPT,Temp);ch=ch =str[i++];; }GetTop(&OPTR, &x);}}

標(biāo)題表達(dá)式樹(shù)的求值算法步驟

① 設(shè)變量lvalue和 rvalue分別用以記錄表達(dá)式樹(shù)中左子樹(shù)和右子樹(shù)的值,初始均為0。
② 如果當(dāng)前結(jié)點(diǎn)為葉子(結(jié)點(diǎn)為操作數(shù)),則返回該結(jié)點(diǎn)的數(shù)值,否則(結(jié)點(diǎn)為運(yùn)算符)執(zhí)行以下操作:
遞歸計(jì)算左子樹(shù)的值記為 lvalue
遞歸計(jì)算右子樹(shù)的值記為 rvalue
根據(jù)當(dāng)前結(jié)點(diǎn)運(yùn)算符的類(lèi)型,將lvalue和rvalue進(jìn)行相應(yīng)運(yùn)算并返回。

int calculate_BiTree(BiTree &T) {int lvalue;int rvalue;char theta;if(T==NULL) return 0;if(T!=NULL){if(T->lchild==NULL&&T->lchild==NULL)return T->data-'0';else{lvalue=calculate_BiTree(T->lchild);rvalue=calculate_BiTree(T->rchild);theta=T->data;return Operate(lvalue,theta,rvalue);} } }

全部代碼(可直接運(yùn)行)

#include<stdio.h> #include<bits/stdc++.h> #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0#define STACK_INIT_SIZE 100 //存儲(chǔ)空間初始分配量 #define STACKINCREMENT 10 //存儲(chǔ)空間分配增量 typedef int Status; typedef char TElemType;//表達(dá)式求值的運(yùn)算類(lèi)型 typedef int ElemType; typedef struct BiNode {TElemType data;struct BiNode *lchild;struct BiNode *rchild; }BiNode,*BiTree; typedef BiTree SBElemType;int preorderTraverse(BiTree T)//二叉樹(shù)的先序遞歸遍歷算法 {if(T==NULL)return 0;else {printf("%c ",T->data);preorderTraverse(T->lchild);preorderTraverse(T->rchild);}} int InorderTraverse(BiTree T)//二叉樹(shù)的中序遞歸遍歷算法 {if(T==NULL)return 0;else {InorderTraverse(T->lchild);printf("%c",T->data);InorderTraverse(T->rchild);}}int PostorderTraverse(BiTree T)//二叉樹(shù)的后序遞歸遍歷算法 {if(T==NULL)return 0;else {PostorderTraverse(T->lchild);PostorderTraverse(T->rchild);printf("%c ",T->data);}}typedef struct {TElemType *base;TElemType *top;int stacksize; }SqStack;//構(gòu)造一個(gè)空棧 Status InitStack(SqStack *S) {S->base = (TElemType *)malloc(STACK_INIT_SIZE * sizeof(TElemType));if(!S->base){printf("內(nèi)存分配失敗!\n");exit(0);}S->top = S->base;S->stacksize = STACK_INIT_SIZE;return OK; }//若棧不為空,則用e返回S的棧頂元素,并返回OK;否則返回ERROR Status GetTop(SqStack *S, TElemType *e) {if(S->top == S->base)return ERROR;*e = *(S->top - 1);return OK; }//插入元素e為新的棧頂元素 Status Push(SqStack *S, TElemType e) {if(S->top - S->base >= STACK_INIT_SIZE) //棧滿, 追加存儲(chǔ)空間{S->base = (TElemType *)realloc(S->base, (S->stacksize + STACKINCREMENT) * sizeof(TElemType));if(!S->base){printf("內(nèi)存分配失敗!\n");exit(OVERFLOW);}S->top = S->base + S->stacksize;S->stacksize += STACKINCREMENT;}*S->top++ = e;return OK; }//若棧不為空,則刪除S的棧頂元素,用e返回其值,并返回Ok;否則返回ERROR Status Pop(SqStack *S, TElemType *e) {if(S->top == S->base)return ERROR;*e = *--S->top;return OK; }typedef struct {SBElemType *base; // 棧底指針SBElemType *top; // 棧頂指針int stacksize; // 棧空間大小 } SqStack_BiTree;void SqStack_BiTree_InitStack(SqStack_BiTree &S) {// 構(gòu)造一個(gè)空棧Sif(!(S.base = (SBElemType *)malloc(STACK_INIT_SIZE * sizeof(SBElemType))))exit(0); // 存儲(chǔ)分配失敗S.top = S.base;S.stacksize = STACK_INIT_SIZE; }void SqStack_BiTree_DestroyStack(SqStack_BiTree &S) {// 銷(xiāo)毀棧S,S不再存在free(S.base);S.base = NULL;S.top = NULL;S.stacksize = 0; }void SqStack_BiTree_Push(SqStack_BiTree &S, SBElemType e) {if(S.top - S.base >= S.stacksize) { // 棧滿,追加存儲(chǔ)空間S.base = (SBElemType *)realloc(S.base, (S.stacksize + STACKINCREMENT) * sizeof(SBElemType));if(!S.base)exit(OVERFLOW); // 存儲(chǔ)分配失敗S.top = S.base + S.stacksize;S.stacksize += STACKINCREMENT;}*(S.top)++ = e; }Status SqStack_BiTree_Pop(SqStack_BiTree &S, SBElemType &e) {// 若棧不空,則刪除S的棧頂元素,用e返回其值,并返回OK;// 否則返回ERRORif(S.top == S.base){//printf("此時(shí)棧為空,不可以再出棧\n");return ERROR;}e = *--S.top;//printf("當(dāng)前出棧的元素的值為:%d\n",e);return OK; }Status SqStack_BiTree_GetTop(SqStack_BiTree S, SBElemType &e) {// 若棧不空,則用e返回S的棧頂元素,并返回OK;// 否則返回ERRORif(S.top > S.base) {e = *(S.top - 1);//printf("輸出棧頂元素為 %d \n",e);return OK;}else{//printf("此時(shí)棧為空,得不到棧頂元素\n");return ERROR;}}//根據(jù)教科書(shū)表3.1,判斷兩符號(hào)的優(yōu)先關(guān)系 char Precede(char t1, char t2) { int i,j; char pre[7][7]={ //運(yùn)算符之間的優(yōu)先級(jí)制作成一張表格 {'>','>','<','<','<','>','>'}, {'>','>','<','<','<','>','>'}, {'>','>','>','>','<','>','>'}, {'>','>','>','>','<','>','>'}, {'<','<','<','<','<','=','0'}, {'>','>','>','>','0','>','>'}, {'<','<','<','<','<','0','='}}; switch(t1){ case '+': i=0; break; case '-': i=1; break; case '*': i=2; break; case '/': i=3; break; case '(': i=4; break; case ')': i=5; break; case '=': i=6; break; } switch(t2){ case '+': j=0; break; case '-': j=1; break; case '*': j=2; break; case '/': j=3; break; case '(': j=4; break; case ')': j=5; break; case '=': j=6; break; } return pre[i][j]; } //判斷c是否為運(yùn)算符 Status In(TElemType c) {switch(c){case '+':case '-':case '*':case '/':case '(':case ')':case '=':return TRUE;default:return FALSE;}}//二元運(yùn)算(a theta b) ElemType Operate(ElemType a, TElemType theta, ElemType b) {TElemType c;switch(theta){case '+':c = a + b;break;case '-':c = a - b;break;case '*':c = a * b;break;case '/':c = a / b;break;}return c; }void EvaluateExpression(BiTree &root,char *str) {SqStack OPTR;InitStack(&OPTR);SqStack_BiTree EXPT; SqStack_BiTree_InitStack(EXPT);char ch,x,theta;BiTree a,b;int i=0;Push(&OPTR, '='); //=是表達(dá)式結(jié)束符ch =str[i++];GetTop(&OPTR, &x);while(ch != '=' || x != '='){if(In(ch)) //是7種運(yùn)算符之一{switch(Precede(x, ch)){case '<': //當(dāng)前已經(jīng)壓棧一個(gè)運(yùn)算符(x)比后一個(gè)運(yùn)算符(c)低時(shí),就將c壓棧Push(&OPTR, ch);ch =str[i++];break;case '='://消除小括號(hào) Pop(&OPTR, &x); //脫括號(hào)并接收下一字符 ch =str[i++]; break;case '>':Pop(&OPTR,&theta);BiTree TEMP;TEMP=(BiNode*)malloc(sizeof(BiNode));if(!TEMP)exit(-1);TEMP->data=theta; SqStack_BiTree_Pop(EXPT,b);SqStack_BiTree_Pop(EXPT,a);TEMP->lchild=a;TEMP->rchild=b;SqStack_BiTree_Push(EXPT,TEMP);root=TEMP;break;}}if(ch>='0'&&ch<='9'){BiTree Temp;Temp=(BiNode*)malloc(sizeof(BiNode));if(!Temp)exit(-1);Temp->data=ch;Temp->lchild=NULL;Temp->rchild=NULL;SqStack_BiTree_Push(EXPT,Temp);ch=ch =str[i++];; }GetTop(&OPTR, &x);}}int calculate_BiTree(BiTree &T) {int lvalue;int rvalue;char theta;if(T==NULL) return 0;if(T!=NULL){if(T->lchild==NULL&&T->lchild==NULL)return T->data-'0';else{lvalue=calculate_BiTree(T->lchild);rvalue=calculate_BiTree(T->rchild);theta=T->data;return Operate(lvalue,theta,rvalue);} } }int main() {BiTree T;char str[1000];int result[100]={0};int number=0;do{printf("輸入表達(dá)式:");gets(str);EvaluateExpression(T,str);result[number]=calculate_BiTree(T);number++;}while(strcmp(str,"=")!=0);for(int j=0;j<number-1;j++){printf("\n表達(dá)式運(yùn)算結(jié)果:%d",result[j]);}}

總結(jié)

以上是生活随笔為你收集整理的数据结构—— 基于二叉树的算术表达式求值的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。