标签:
一、基本要求:
(
1 ) 利用二叉树后序遍历来实现表达式的转换,同时可以使用实验三的结果来求解后缀表达式的值。
输出逆波兰表达式
运算结果为:输出运算后的结果
测试数据
输入: 21+23*( 12-6)
输出: 21 23 12 6 -*+
二、基本思路
中缀表达式-》二叉树-》后序遍历-》计算
1.中缀表达式-》二叉树の需要考虑的问题:
操作符的等级设置
最上面的等级最小
设计函数ToTree来实现此过程:该过程递归
递归的判断:
1.怎样按同类更小问题解决:找到当前字符串中的最小等级操作符给data,左边的表达式给左子树,右边的表达式给右子树,左边和右边分别是一个更短的字符串的分支问题
2.各个递归怎么减小问题规模:左边和右边分别是一个更短的字符串的分支问题
3.什么情况可以当做基例:到叶子节点的情况,也就是说表达式里面没有运算符了,然后data=操作数,左右子树=NULL
4.能否最后达到基例:可以
要么我写个P啊
首先先要把各个字符都赋好等级,我把数字也赋值了,最开始没有,还写了个函数提取了所有操作符,后来发现这样很难把等级数组和算式相对应,又推倒重新写了一次,我心在滴血!
,如果把数字都负上就可以对上了,查找最小的时候下标是可以返回的,对应了相应的操作符。
for(i=0;suanshi[i]!='\0';i++)
{
if(suanshi[i]=='(')
{
duoshaoji++;//记录第几层括号,几层括号就把里面的运算符的等级提高n*100<img alt="惊讶" src="http://static.blog.csdn.net/xheditor/xheditor_emot/default/ohmy.gif" />?它好聪明!
dengji[i]=0;
dengji[i]=0;
}
else if(suanshi[i]==')')
{
duoshaoji--;
dengji[i]=0;
}
else if(suanshi[i]=='+'||suanshi[i]=='-')
dengji[i]=1+duoshaoji*100;
else if(suanshi[i]=='*'||suanshi[i]=='/')
dengji[i]=2+duoshaoji*100;
else
dengji[i]=-1;
}
因为在树中我们不需要(),所以()肯定不能到树里,但是我们还需要()来辅助判断运算等级,经过分析发现,只要把最开始进函数的表达式两边的括号去掉就行了,这样就对后面的不影响了。
if(suanshi[0]=='('&&suanshi[length]==')')
{
suanshi++;
suanshi[length-1]='\0';
}//去括号的过程,只去那种开头是括号结尾是括号的情况
最开始我设的树节点是一个char,后来用了什么ASII的编码把char-》int的变来变去,还是不成,最后只好托马重写
,改成了char数组的形式,这样就随之而来一些问题,在之后的后序遍历赋值里会遇到。
算起来又是我之前写的逆波兰的程序的错误,我觉得有时间的话我真的应该把逆波兰的程序在写一遍了,
我不会说我上节课改逆波兰改了4次吧,算上这回应该有5、6次了吧,心碎,不过也确实怪我自己考虑问题不全,没有想到数字和操作符的数目可能不相符的情况,又让这个猪脚挑出了猫饼
,以后我要叫他猫饼猪脚。这么萌的名字一定配的上他用的可爱的少女心的粉色本本~
void ToTree(BiTree &T,char *suanshi)
{
int duoshaoji=0,i=0,length=suanshilength(suanshi),j=0,min=0,minn=0,k=0;
char *lsuanshi=NULL,*rsuanshi=NULL,exc=NULL;
if(suanshi[0]=='('&&suanshi[length]==')')
{
suanshi++;
suanshi[length-1]='\0';
}//去括号的过程,只去那种开头是括号结尾是括号的情况
length=suanshilength(suanshi);
int *dengji;
dengji=(int *)malloc((length+1)*sizeof(int));
for(i=0;suanshi[i]!='\0';i++)
{
if(suanshi[i]=='(')
{
duoshaoji++;
dengji[i]=0;
}
else if(suanshi[i]==')')
{
duoshaoji--;
dengji[i]=0;
}
else if(suanshi[i]=='+'||suanshi[i]=='-')
dengji[i]=1+duoshaoji*100;
else if(suanshi[i]=='*'||suanshi[i]=='/')
dengji[i]=2+duoshaoji*100;
else
dengji[i]=-1;
}
T=(BiTreeNode *)malloc(sizeof(BiTreeNode));
if(checkfuhao(suanshi))//有符号的情况
{
for(j=1;j<length+1;j++)
{
if(dengji[j]>0)
{
min=dengji[j];
minn=j;
break;
}
}
for(j=1;j<length+1;j++)
{
if(dengji[j]>0&&min>dengji[j])
{
min=dengji[j];
minn=j;
}
}
T->data[0]=suanshi[minn];
T->data[1]='\0';
//printf("****%c\n",T->data);
lsuanshi=suanshi;
lsuanshi[minn]='\0';
rsuanshi=&suanshi[minn+1];
ToTree(T->leftChild,lsuanshi);
ToTree(T->rightChild,rsuanshi);
}
else//没有符号的情况
{
strcpy(T->data,suanshi);
T->leftChild=NULL;
T->rightChild=NULL;
}
free(dengji);
}
,我觉得自己做的好蠢
void preorder(BiTree t,char *p)
{
int k=0,x=0;
if(t)
{
preorder(t->leftChild,p);
preorder(t->rightChild,p);
if(t->data[0]=='+'||t->data[0]=='-'||t->data[0]=='/'||t->data[0]=='*')
{printf("%c ",t->data[0]);
if(*p!='\0')
{ strcat(p," ");
strcat(p,t->data);}
else
{
strcat(p,t->data);}
}
else
{printf("%s ",t->data);
if(*p!='\0')
{ strcat(p," ");
strcat(p,t->data);}
else
{
strcat(p,t->data);}
}
}
}

其他的是上次的逆波兰~
贴一下所有代码
//
#include "stdafx.h"
#define MAXNUM 100
#define OVERFLOW -2;
#include<iostream>
#include<string>
#include<stdlib.h>
#include<stdio.h>
#include<iomanip>
using namespace std;
char suan[MAXNUM],*p=suan;
typedef struct node
{
struct node *leftChild;
struct node *rightChild;
char data[15];
}BiTreeNode, *BiTree;
int suanshilength(char *suanshi)
{
int i=0,k=0;
for(i=0;suanshi[i]!='\0';i++)
{
k++;
}
k--;
return k;
}
bool checkkuohao(char *suanshi)
{
int i=0,k=0;
bool flag=1;
for(i=0;suanshi[i]!='\0';i++)
{
if(k<0)
{flag=0;break;
}
if(suanshi[i]=='(')
k++;
if(suanshi[i]==')')
k--;
}
if(k!=0)
flag=0;
return flag;
}
bool checkfuhao(char *suanshi)
{
int i=0;
bool flag=0;
for(i=0;suanshi[i]!='\0';i++)
{
if(suanshi[i]=='+'||suanshi[i]=='-'||suanshi[i]=='*'||suanshi[i]=='/')
{
flag=1;
}
}
return flag;
}
void ToTree(BiTree &T,char *suanshi)
{
int duoshaoji=0,i=0,length=suanshilength(suanshi),j=0,min=0,minn=0,k=0;
char *lsuanshi=NULL,*rsuanshi=NULL,exc=NULL;
if(suanshi[0]=='('&&suanshi[length]==')')
{
suanshi++;
suanshi[length-1]='\0';
}//去括号的过程,只去那种开头是括号结尾是括号的情况
length=suanshilength(suanshi);
int *dengji;
dengji=(int *)malloc((length+1)*sizeof(int));
for(i=0;suanshi[i]!='\0';i++)
{
if(suanshi[i]=='(')
{
duoshaoji++;
dengji[i]=0;
}
else if(suanshi[i]==')')
{
duoshaoji--;
dengji[i]=0;
}
else if(suanshi[i]=='+'||suanshi[i]=='-')
dengji[i]=1+duoshaoji*100;
else if(suanshi[i]=='*'||suanshi[i]=='/')
dengji[i]=2+duoshaoji*100;
else
dengji[i]=-1;
}
T=(BiTreeNode *)malloc(sizeof(BiTreeNode));
if(checkfuhao(suanshi))//有符号的情况
{
for(j=1;j<length+1;j++)
{
if(dengji[j]>0)
{
min=dengji[j];
minn=j;
break;
}
}
for(j=1;j<length+1;j++)
{
if(dengji[j]>0&&min>dengji[j])
{
min=dengji[j];
minn=j;
}
}
T->data[0]=suanshi[minn];
T->data[1]='\0';
//printf("****%c\n",T->data);
lsuanshi=suanshi;
lsuanshi[minn]='\0';
rsuanshi=&suanshi[minn+1];
ToTree(T->leftChild,lsuanshi);
ToTree(T->rightChild,rsuanshi);
}
else//没有符号的情况
{
strcpy(T->data,suanshi);
T->leftChild=NULL;
T->rightChild=NULL;
}
free(dengji);
}
void preorder(BiTree t,char *p)
{
int k=0,x=0;
if(t)
{
preorder(t->leftChild,p);
preorder(t->rightChild,p);
if(t->data[0]=='+'||t->data[0]=='-'||t->data[0]=='/'||t->data[0]=='*')
{printf("%c ",t->data[0]);
if(*p!='\0')
{ strcat(p," ");
strcat(p,t->data);}
else
{
strcat(p,t->data);}
}
else
{printf("%s ",t->data);
if(*p!='\0')
{ strcat(p," ");
strcat(p,t->data);}
else
{
strcat(p,t->data);}
}
}
}
typedef struct nibolanstack //建立栈类
{
double *base;
double *top;
int stacksize;
}nibolans;
bool InitStack(nibolans &S){ //创建一个空栈
S.base=(double *)malloc(50*sizeof(double));
// if(!S.base) exit(OVERFLOW);
S.top=S.base;
S.stacksize=50;
return 1;
}
bool push(nibolans &S,double e) //插入元素
{
if(S.top-S.base>=S.stacksize)
{
S.base=(double *)realloc(S.base,(S.stacksize+20)*sizeof(double));
if(!S.base)
exit(-2);
S.top=S.base+S.stacksize;
S.stacksize=S.stacksize+20;
}
*(S.top)=e;
S.top++;
return 1;
}
bool pop(nibolans &S,double &e) //出栈
{
if(S.top==S.base)
return 0;
S.top--;
e=*S.top;
return 1;
}
void check(char s[],nibolans &S)
{
char *p=s,q[10];
int i=0,k=0;
double m,x,y,z;
// cout<<s<<endl;
while(*p!='#')
{
if(*p==' ')
{
// cout<<endl;
m=atof(q);
// cout<<m<<endl;
if(m!=0)
push(S,m);
for(int j=0;j<i;j++)
{
q[j]='\0';//char型置空
}
i=0;
}
else
{
// cout<<*p<<" ";
// cout<<(*p=='+');
if((*p=='+')||(*p=='-')||(*p=='*')||(*p=='/'))
{
pop(S,x);
pop(S,y);
if(*p=='+')
{
z=x+y;
push(S,z);
}
if(*p=='-')
{
z=y-x;
push(S,z);
}
if(*p=='*')
{
z=x*y;
push(S,z);
}
if(*p=='/')
{
z=y/x;
push(S,y/x);
}
}
else
{
q[i]=*p;
i++;
}
}
p++;
}
// return z;
}
bool checkk(char s[])
{
bool flag=0;
char *p=s;
char *q=s;
while(*q!='\0')
{
if((*q=='+')||(*q=='-')||(*q=='*')||(*q=='/'))
{
flag=1;
}
q++;
}
while(*p!='\0')
{
if((*p!='0')&&(*p!='1')&&(*p!='2')&&(*p!='3')&&(*p!='4')&&(*p!='5')&&(*p!='6')&&(*p!='7')&&(*p!='8')&&(*p!='9')&&(*p!='+')&&(*p!='-')&&(*p!='*')&&(*p!='/')&&(*p!=' ')&&(*p!='#'))
{
flag=0;
}
p++;
}
return flag;
}
int main(int argc, char* argv[])
{
char suanshi[MAXNUM];
double jieguo;
BiTree BT;
nibolans S;
InitStack(S);
printf("请输入中缀表达式:\n");
gets(suanshi);
if(checkkuohao(suanshi))
{
ToTree(BT,suanshi);
preorder(BT,p);
cout<<endl;
strcat(suan,"#");
puts(suan);
if(checkk(suan))
{
check(suan,S);
pop(S,jieguo);
cout<<fixed<<setprecision(2)<<jieguo;
}
else
cout<<"表达式错误!"<<endl;
}
else
cout<<"表达式错误!"<<endl;
return 0;
}
接下来是我几个不太熟悉的函数总结一下:
1.复制字符串
strcpy(T->data,suanshi);把后面的复制到前面的地方。C语言标准库函数strcpy,把从src地址开始且含有‘\0‘结束符的字符串复制到以dest开始的地址空间。
2.字符串后追加字符串
strcat(p,t->data)把p指向的字符串追加到t-》data后面,两者都得有‘、0’
标签:
原文地址:http://blog.csdn.net/yanapupa/article/details/51348224