无聊小练一下数据结构,表达式求值
#include <iostream.h> #include <stdio.h> #include <stdlib.h> 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; /////////////////+, -, *, /, (, ),\0,////////// int priority[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, 0, 1, 1, 1, 1, 0, 1, 1, -1,-1,-1,-1,-1, 0, 0}; 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) //确定优先性函数 { int i=0,j=0; switch(top){ 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 '\0': i=6; break; default: printf("error\n"); } switch(follow){ 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 '\0': j=6; break; default: printf("error\n"); } switch(priority[i][j]){ case 0: return '='; case 1: return '>'; case -1: return '<'; } return 'e'; } 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=temp1->number; // free(temp1); }else{ //左边结点已经是数字了 leftValue=tree->lchild->number; } if(tree->rchild->flag==2){ temp2=CalculateTree(tree->rchild); rightValue=temp2->number; //free(temp2); }else{ rightValue=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(", "); } void main() { BiTree L; InitExpTree(L); printf("前缀式输出:"); PrePrintTree(L); printf("\n中缀式输出:"); MidPrintTree(L); printf("\n后缀式输出:"); FolPrintTree(L); printf("\n层次输出:"); ccPrintTree(L); printf("\n值为:%f",CalculateTree(L)->number); printf("\n广义表为:"); TablePrintTree(L,0); }