#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
typedef struct BITNODE
{
int flag; //0沒用過,1數位元組點,2符號節點
char sign;
float number;
struct BITNODE *lchild,*rchild;
}BitNode,*BiTree;
typedef struct LINKLIST
{
struct BITNODE *treeNode;
struct LINKLIST *nextNode;
struct LINKLIST *lastNode;
}linkNode,*LinkList;
int stackTopBiTree=-1; //堆疊頂指標
int stackTopSign=-1;
BiTree stackB[100];
char stackC[100];
BiTree popB() //進出堆疊函式
{
return stackB[stackTopBiTree--];
}
void pushB(BiTree biTree)
{
stackB[++stackTopBiTree]=biTree;
}
///
char popC()
{
return stackC[stackTopSign--];
}
void pushC(char sign)
{
stackC[++stackTopSign]=sign;
}
BiTree outList(LinkList &list)
{
if(!list->nextNode) return NULL;
if(!list->nextNode->nextNode) list->lastNode=list; //如果全出完了把最后
LinkList tempList; //結點放在頭結點
BiTree tempTree;
tempList=list->nextNode;
tempTree=list->nextNode->treeNode;
list->nextNode=list->nextNode->nextNode;
free(tempList); //釋放鏈表接點
return tempTree;
}
void inList(LinkList &list,BiTree treeNode)
{
LinkList listNode;
listNode=(LinkList)malloc(sizeof(linkNode));
listNode->treeNode=treeNode; //從最后一個進堆疊
listNode->nextNode=NULL;
listNode->lastNode=NULL;
list->lastNode->nextNode=listNode; //鏈表最后一個指向下一個
list->lastNode=listNode; //更新最后一個的位置
}
void ccPrintTree(BiTree node)
{
if(!node){
printf("空樹!");
return;
}
LinkList list;
list=(LinkList)malloc(sizeof(LinkList));
list->nextNode=NULL;
list->treeNode=NULL;
list->lastNode=list;
inList(list,node);
BiTree temp;
while(list->nextNode) {
temp = outList(list);
if(temp->lchild) inList(list,temp->lchild); //還有結點入堆疊
if(temp->rchild) inList(list,temp->rchild);
if(temp->flag==1) printf("\t%f",temp->number);
else printf("\t%c",temp->sign);
}
}
void InitHead(BiTree &L) //初始化樹
{
L=(BiTree)malloc(sizeof(BitNode));
L->lchild=NULL;
L->rchild=NULL;
L->sign='\0';
L->number=0;
L->flag=0;
}
float reap(char *exp,int position1,int position2) //獲得兩個算符之間的數字
{
int pot=position1+1,i=0; //pot是小數點的位置
float numHigh=0.0,numLow=0.0; //存放數字的小數點之前和之后的數
char *p=exp+position1+1;
while((*(p+i)!='.')&&(pot!=position2)) {
i++;
pot++;
}
for(int j=0;j<pot-position1-1;j++){ //計算數字
numHigh+=(*(p+j)-'0');
numHigh*=10.0;
}
numHigh/=10.0;
for(int k=0;k<position2-pot-1;k++) { //小數部分的計算
numLow+=(*(exp+position2-1-k)-'0');
numLow/=10.0;
}
return numHigh+numLow;
}
BiTree CreatTreeNode(BiTree nodeA,char sign,BiTree nodeB)
{
BiTree signNode;
signNode=(BiTree)malloc(sizeof(BiTree)); //創建樹接點
signNode->lchild=nodeA;
signNode->rchild=nodeB;
signNode->sign=sign;
signNode->flag=2;
return signNode;
}
char Precede(char top,char follow) //確定優先性函式
void InitExpTree(BiTree &L)
{
InitHead(L);
printf("please input the express:");
char *exp=(char*)malloc(sizeof(char)*255);
scanf("%s",exp); //獲得運算式
int haveNum=0,i=0;
char sign;
int position1=-1,position2=1; //記錄符號位置
stackTopBiTree=-1; //初始化堆疊頂
stackTopSign=-1;
pushC('\0'); //把空字符壓入堆疊
while(*(exp+i)!='\0'||stackC[stackTopSign]!='\0') { //當都為結束符號時
if((*(exp+i)<'0'||*(exp+i)>'9')&&(*(exp+i)!='.')){
position2=i; //新的符號的位置
if(haveNum==1) { //出現了數字開關,需要提取數字
BiTree nodeNum =(BiTree)malloc(sizeof(BiTree));
nodeNum->flag=1;
nodeNum->lchild=NULL;
nodeNum->rchild=NULL;
nodeNum->number=reap(exp,position1,position2);
pushB(nodeNum);
haveNum=0;
}
switch(Precede(stackC[stackTopSign],*(exp+i))) { //比較
case '<':
pushC(*(exp+i)); //堆疊頂優先小,壓堆疊
position1=position2; //更新符號位置
i++; //運算式后移
break;
case '=':
popC(); //脫括號
position1=position2;
i++;
break;
case '>':
sign=popC(); //符號和數出堆疊進行計算
BiTree t1,t2;
t2=popB();
t1=popB();
pushB(CreatTreeNode(t1,sign,t2));
break;
default:
printf("errorout!"); //出錯保護
break;
}
}else {
haveNum=1;
i++;
}
}
L=popB();
}
BiTree CalculateTree(BiTree tree)
{
float leftValue,rightValue;
BiTree temp1,temp2;
if(tree->lchild->flag==2) { //左邊結點是符號,繼續算
temp1=CalculateTree(tree->lchild);
leftValue=https://bbs.csdn.net/topics/temp1->number;
// free(temp1);
}else{ //左邊結點已經是數字了
leftValue=https://bbs.csdn.net/topics/tree->lchild->number;
}
if(tree->rchild->flag==2){
temp2=CalculateTree(tree->rchild);
rightValue=https://bbs.csdn.net/topics/temp2->number;
//free(temp2);
}else{
rightValue=https://bbs.csdn.net/topics/tree->rchild->number;
}
BiTree newNode=(BiTree)malloc(sizeof(BiTree));
newNode->flag=1; //把算好后的結果組成新的數字結點回傳
newNode->lchild=NULL;
newNode->rchild=NULL;
switch(tree->sign)
{
case '+': newNode->number=leftValue+rightValue;
break;
case '-': newNode->number=leftValue-rightValue;
break;
case '*': newNode->number=leftValue*rightValue;
break;
case '/': newNode->number=leftValue/rightValue;
break;
}
return newNode;
}
void PrePrintTree(BiTree node) //先序輸出
{
if(node->flag==2) printf("%c ",node->sign);
else printf("%f ",node->number);
if((node->lchild)) PrePrintTree(node->lchild);
if((node->rchild)) PrePrintTree(node->rchild);
}
void MidPrintTree(BiTree node) //中序輸出
{
if((node->lchild)) MidPrintTree(node->lchild);
if(node->flag==2) printf("%c ",node->sign);
else printf("%f ",node->number);
if((node->rchild)) MidPrintTree(node->rchild);
}
void FolPrintTree(BiTree node) //后序輸出
{
if((node->lchild)) FolPrintTree(node->lchild);
if((node->rchild)) FolPrintTree(node->rchild);
if(node->flag==2) printf("%c ",node->sign);
else printf("%f ",node->number);
}
void DeleteTree(BiTree node)
{
if(!node)
return ;
if((node->lchild==NULL)&&(node->lchild==NULL)){
free(node);
return;
}
if(node->lchild) DeleteTree(node->lchild);
if(node->rchild) DeleteTree(node->rchild);
}
void TablePrintTree(BiTree node,int tt) //廣義表輸出
{
int t=0,tSign=0; //t是右括號開關,tt和tSign都是,開關
if(node->flag==2) {
printf("%c(",node->sign); //輸出符號
if(tt) tSign=1; //如果符號結點也是左結點,后面括號后面也要加一個標點
} else {
printf("%f ",node->number);
if(tt) printf(", "); //如果是左結點輸出點號
t=1;
}
if((node->lchild)) TablePrintTree(node->lchild,1);
if((node->rchild)) TablePrintTree(node->rchild,0);
if(t==0) printf(")"); //如果是符號的回圈就輸出右括號
if(tSign) printf(", ");
}
int main()
{
BiTree L;
InitExpTree(L);
printf("前綴式輸出:");
PrePrintTree(L);
printf("\n中綴式輸出:");
MidPrintTree(L);
printf("\n后綴式輸出:");
FolPrintTree(L);
printf("\n值為:%f",CalculateTree(L)->number);
printf("\n廣義表為:");
TablePrintTree(L,0);
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/239333.html
標籤:C++ 語言
上一篇:關于指標的回圈 小問題
下一篇:求助
