利用树求解算术表达式的值
利用樹求解算術表達式的值
?
#include <stdio.h>
#include <string.h>
#include <malloc.h>
//#include "btree.h"
#define MaxSize 100
#include<stdlib.h>
typedef struct Node
{
?? ?char data;
?? ?struct Node *lchild;
?? ?struct Node *rchild;
}BTNode,*BTree;
//用s[i]到s[j]之間的字符串,構造二叉樹的表示形式
BTNode *CreateTree(char s[],int i,int j)
{
?? ?BTNode *p;
?? ?int k,plus=0,posi;
?? ?if (i==j) //i和j相同,意味著只有一個字符,構造的是一個葉子節點
?? ?{
?? ??? ?p=(BTNode *)malloc(sizeof(BTNode)); //分配存儲空間
?? ??? ?p->data=s[i]; //值為s[i]
?? ??? ?p->lchild=NULL;
?? ??? ?p->rchild=NULL;
?? ??? ?return p;
?? ?}
?? ?//以下為i!=j的情況
?? ?for (k=i; k<=j; k++)
?? ??? ?if (s[k]=='+' || s[k]=='-')
?? ??? ?{
?? ??? ??? ?plus++;
?? ??? ??? ?posi=k; //最后一個+或-的位置
?? ??? ?}
?? ??? ?if (plus==0) //沒有+或-的情況(因為若有+、-,前面必會執行plus++)
?? ??? ??? ?for (k=i; k<=j; k++)
?? ??? ??? ??? ?if (s[k]=='*' || s[k]=='/')
?? ??? ??? ??? ?{
?? ??? ??? ??? ??? ?plus++;
?? ??? ??? ??? ??? ?posi=k;
?? ??? ??? ??? ?}
?? ??? ??? ??? ?//以上的處理考慮了優先將+、-放到二叉樹較高的層次上
?? ??? ??? ??? ?//由于將來計算時,運用的是后序遍歷的思路
?? ??? ??? ??? ?//處于較低層的乘除會優先運算
?? ??? ??? ??? ?//從而體現了“先乘除后加減”的運算法則
?? ??? ??? ??? ?//創建一個分支節點,用檢測到的運算符作為節點值
?? ??? ??? ??? ?if (plus!=0)
?? ??? ??? ??? ?{
?? ??? ??? ??? ??? ?p=(BTNode *)malloc(sizeof(BTNode));
?? ??? ??? ??? ??? ?p->data=s[posi]; //節點值是s[posi]
?? ??? ??? ??? ??? ?p->lchild=CreateTree(s,i,posi-1); //左子樹由s[i]至s[posi-1]構成
?? ??? ??? ??? ??? ?p->rchild=CreateTree(s,posi+1,j); //右子樹由s[poso+1]到s[j]構成
?? ??? ??? ??? ??? ?return p;
?? ??? ??? ??? ?}
?? ??? ??? ??? ?else //若沒有任何運算符,返回NULL
?? ??? ??? ??? ??? ?return NULL;
}
int find_split(char express[], int start, int end)
{
?? ?int tag = -1;
?? ?if (express[start] == '(' && express[end] == ')')
?? ?{
?? ??? ?++start;
?? ??? ?--end;
?? ?}
?? ?int is_in_braket = 0;
?? ?int more_grade = 0;
?? ?for (int i = start; i <= end; i++)
?? ?{
?? ??? ?if (express[i] == '(')
?? ??? ??? ?++is_in_braket;
?? ??? ?else if (express[i] == ')')
?? ??? ??? ?--is_in_braket;
?? ??? ?if ((express[i] == '+' || express[i] == '-')
?? ??? ??? ?&& is_in_braket == 0)
?? ??? ?{
?? ??? ??? ?more_grade = 1;
?? ??? ??? ?tag = i; //無break, 找最后一個符合條件的運算符, 取頂級的+和-
?? ??? ?}
?? ??? ?else if ((express[i] == '*' || express[i] == '/')
?? ??? ??? ?&& more_grade == 0
?? ??? ??? ?&& is_in_braket == 0)
?? ??? ?{
?? ??? ??? ?tag = i; //無break, 找最后一個符合條件的運算符
?? ??? ?}
?? ?}
?? ?return tag;
}
BTree Creat_Btree( char *express, int start, int end)
{
?? ?BTree pTree = NULL;
?? ?if (start == end)
?? ?{
?? ??? ?pTree = (BTree)malloc(sizeof(BTNode));
?? ??? ?pTree->data = express[start];
?? ??? ?pTree->lchild = NULL;
?? ??? ?pTree->rchild = NULL;
?? ?}
?? ?else
?? ?{ ? //遞歸調用, 各自創建左右的表達式的對應二叉樹
?? ??? ?int tag = find_split(express, start, end);
?? ??? ?if (tag < 0)
?? ??? ?{
?? ??? ??? ?printf("1.invalid express, exit.\n");
?? ??? ??? ?exit(-1);
?? ??? ?}
?? ??? ?else
?? ??? ?{
?? ??? ??? ?pTree = (BTree)malloc(sizeof(BTNode));
?? ??? ??? ?pTree->data = express[tag];
?? ??? ?}
?? ??? ?if (express[start] == '(' && express[end] == ')')
?? ??? ?{
?? ??? ??? ?++start;
?? ??? ??? ?--end;
?? ??? ?}
?? ??? ?pTree->lchild = Creat_Btree(express, start, tag - 1);
?? ??? ?pTree->rchild = Creat_Btree(express, tag + 1, end);
?? ?}
?? ?return pTree;
}
double post_traverser_calc(BTree pTree)
{
?? ?if (pTree == NULL)
?? ??? ?return -1;
?? ?else if ('0' <= pTree->data &&pTree->data <= '9')
?? ??? ?return pTree->data - '0';
?? ?else if(pTree->data=='+')
?? ??? ?return post_traverser_calc(pTree->lchild) + post_traverser_calc(pTree->rchild);
?? ?else if(pTree->data=='-')
?? ??? ?return post_traverser_calc(pTree->lchild) - post_traverser_calc(pTree->rchild);
?? ?else if(pTree->data=='*')
?? ??? ?return post_traverser_calc(pTree->lchild) * post_traverser_calc(pTree->rchild);
?? ?else if(pTree->data=='/')
?? ??? ?return post_traverser_calc(pTree->lchild) / post_traverser_calc(pTree->rchild);
}
double CalcuValue(BTNode *b)
{
?? ?double v1,v2;
?? ?if (b==NULL)
?? ??? ?return 0;
?? ?if (b->lchild==NULL && b->rchild==NULL) //葉子節點,應該是一個數字字符(本項目未考慮非法表達式)
?? ??? ?return b->data-'0'; //葉子節點直接返回節點值,結點中保存的數字用的是字符形式,所以要-'0'
?? ?v1=CalcuValue(b->lchild); //先計算左子樹
?? ?v2=CalcuValue(b->rchild); //再計算右子樹
?? ?switch(b->data) //將左、右子樹運算的結果再進行運算,運用的是后序遍歷的思路
?? ?{
?? ?case '+':
?? ??? ?return v1+v2;
?? ?case '-':
?? ??? ?return v1-v2;
?? ?case '*':
?? ??? ?return v1*v2;
?? ?case '/':
?? ??? ?if (v2!=0)
?? ??? ??? ?return v1/v2;
?? ??? ?else
?? ??? ??? ?abort();
?? ?}
}
void TreePrint(BTree T,int level)?
/*按樹狀打印的二叉樹*/?
{ ??
? ? int i;
? ? if(T==NULL)?? ??? ??? ??? ??? ?/*如果指針為空,返回上一層*/?
? ? ? ? return;
? ? TreePrint(T->rchild,level+1);/*打印右子樹,并將層次加1*/?
? ? for(i=0;i<level;i++)?? ??? ??? ?/*按照遞歸的層次打印空格*/?
? ? ? ? printf(" ? ");
? ? printf("%c\n",T->data);?? ??? ?/*輸出根結點*/?
? ? TreePrint(T->lchild,level+1);/*打印左子樹,并將層次加1*/?
}
void DestroyBTree(BTree *T)
/*銷毀二叉樹操作*/
{
?? ?if(*T) ?? ??? ??? ??? ??? ??? ??? ?/*如果是非空二叉樹*/
?? ?{
?? ??? ?if((*T)->lchild)
?? ??? ??? ?DestroyBTree(&((*T)->lchild));
?? ??? ?if((*T)->rchild)
?? ??? ??? ?DestroyBTree(&((*T)->rchild));
?? ??? ?free(*T);
?? ??? ?*T=NULL;
?? ?}
}
int main()
{
?? ?BTNode *b;
?? ?char s[MaxSize]="1+2*3-4/5";
?? ?printf("算術表達式%s\n",s);
?? ?/*
?? ?b=CreateTree(s,0,strlen(s)-1);
?? ?printf("對應二叉樹:\n");
?? ?TreePrint(b,0);
?? ?printf("\n表達式的值:%g\n",CalcuValue(b));
?? ?DestroyBTree(&b);
?? ?*/
?? ?double result=0;
?? ?BTree express_tree = Creat_Btree(s, 0, strlen(s)-1);
?? ?result=post_traverser_calc(express_tree);
?? ?printf("后綴表達式:");
?? ?post_traverser_calc(express_tree);
?? ?printf("\n");
?? ?printf("表達式結果為:%.2f\n", result);
?? ?return 0;
}
總結
以上是生活随笔為你收集整理的利用树求解算术表达式的值的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【二叉树】先序序列为a,b,c,d 的不
- 下一篇: 数据结构C语言实现课后第1-2章答案