码迷,mamicode.com
首页 > 其他好文 > 详细

四则运算表达式求值の各种心碎

时间:2016-05-12 23:53:04      阅读:313      评论:0      收藏:0      [点我收藏+]

标签:

实验三---四则运算表达式求值

一、基本要求:

( 1 ) 利用二叉树后序遍历来实现表达式的转换,同时可以使用实验三的结果来求解后缀表达式的值。

( 2) 输入输出格式:
输入格式:在字符界面上输入一个中缀表达式,回车表示结束。
请输入表达式:
输入一个中缀表达式
输出格式:如果该中缀表达式正确,那么在字符界面上输出其后缀表达式,其中后
缀表达式中两相邻操作数之间利用空格隔开;如果不正确,在字符界面上输出表达式错误提示。
逆波兰表达式为:

输出逆波兰表达式

运算结果为:输出运算后的结果

测试数据
输入: 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型不符合,怎么办?

最开始我设的树节点是一个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);
} 


  • 进行后序遍历时:要注意我们后序遍历输出的同时,主要的操作是把后序遍历的结果给到逆序的字符串里,这个要用到strcat……全都是我的鱼唇的想法,大家有好的思路可以告诉我技术分享,我觉得自己做的好蠢技术分享




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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!