【新手 表达式求值】 顺序栈实现表达式求值

这几天一直在写表达式求值,但是蛋疼的是老出错,最后没办法只好重写,大哭好不容易终于写出来了,哎 纪念一下大笑

表达式求值的实现:
使用栈结构:1.顺序栈 2.链栈


顺序栈的结构为
typedef struct
{
SElemType *base; //这个指向栈低
SElemType *Top; //这个指向栈顶元素的下一个空位置
int stacksize; //顺序栈的大小,栈当前的最大容量
}SqStack;


需要实现的函数
1.构造一个空栈S
InitStack(SqStack &S)


2.吧元素压入栈中插入元素e进入栈顶
Push(Sqstack &S , SElemType e)


3.得到栈顶元素,返回数据类型
SElemType GetTop(SqStack &S)


4.吧元素从栈顶删除,并返回元素值
SElemType Pop(SqStack &S)


5.判断是字符还是数值
int In(char c)


6.比较字符栈的栈顶字符和当前字符的优先级
如果当前优先级高那压入栈中,否则先进行计算
Precede(char c1 , char c2)


7.进行计算的函数,判断是应该进行什么计算的函数
Operate(int a , char theta , int b)


8.关键算法函数
EvaluateExpression()


最先开始用的链栈结构写的,结果各种乱起八糟的错误,实在写不下去了,只好重写!哭


//功能:表达式求值
//时间:2014年4月23日16:22:24
//作者:cutter_point

#include<iostream>
#include<stdio.h>
#include<stdlib.h>

using namespace std;


//首先得有一个栈,存放运算符
//链栈
typedef struct LStack1
{
	char c;		//存放运算符
	struct LStack1 *next;
}*PLStack1;

typedef struct LStack2
{
	double i;		//存放表达式的数据值
	struct LStack2 *next;
}*PLStack2;

/************栈函数****************/

//创建一个空链栈,这种写两遍好累啊,能用模板么?
void InitStack(PLStack1 &S)
{
	S=NULL;
}

void InitStack(PLStack2 &S)
{
	S=NULL;
}

//Push压入字符元素
void Push1(PLStack1 &S , char c)
{
	PLStack1 p;
	p=(PLStack1)malloc(sizeof(LStack1));
	p->c=c;
	p->next=NULL;
	S->next=p;
	S=p;
}


void Push2(PLStack2 &S , double i)
{
	PLStack2 p;
	p=(PLStack2)malloc(sizeof(LStack2));
	p->i=i;
	p->next=S;
	S=p;
}


//Pop弹出字符元素
char Pop1(PLStack1 &S , char c)
{
	PLStack1 p;
	c=S->c;
	p=S;
	S=S->next;
	free(p);
	return c;		//把c的值返回出去,因为这是局部变量
	
}

double Pop2(PLStack2 &S , double i)
{
	PLStack2 p;
	i=S->i;
	p=S;
	S=S->next;
	free(p);
	//cout<<"这个数值是:"<<i<<endl;
	return i;		//把c的值返回出去,因为这是局部变量
	
}

//各种函数
//取得栈顶元素,字符栈
char GetTop1(PLStack1 &S)
{
	return S->c;
}

double GetTop2(PLStack2 &S)		//这个算是重载了吧!
{
	return S->i;
}

//判断是运算的字符
int In(char c)
{
	int i=0;

	switch(c)
	{
	case '+': case '-': case '*': case '/':
	case '(': case ')': case '#':
		i++;
		break;
	}

	return i;
}

//Precede函数的使用,判断优先级的大小
char Precede(char c1 , char c2)
{
	char c3;

	if(c1 == '+' || c1 == '-')
	{
		switch(c2)		//判断+和'+','-'的优先级,前面是+号,c2是后面出现的
		{
		case '+': case '-': case ')': case '#':
			c3='>';break;
		case '*': case '/': case '(':
			c3='<';break;
		default :
			cout<<"喊你一声逗比,你可敢应1?"<<endl;break;
		}
	}else if(c1 == '*' || c1 == '/')
	{
		switch(c2)	//判断+和'*','/'的优先级,前面是+号,c2是后面出现的
		{
		case '+': case '-': case ')': case '#': case '*': case '/': 
			c3='>';break;
		case '(':
			c3='<';break;
		default :
			cout<<"喊你一声逗比,你可敢应2?"<<endl;break;
		}
	}else if(c1 == '(')
	{
		switch(c2)	//判断+和'('的优先级,前面是+号,c2是后面出现的
		{
		case '+': case '-': case '(': case '*': case '/': 
			c3='<';break;
		case ')':
			c3='=';break;
		default :
			cout<<"喊你一声逗比,你可敢应3?"<<endl;break;
		}
	}else if(c1 == ')')		//判断‘)’和其他符号的优先级
	{
		if(c2 != '(')
		{
			c3='>';
		}
	}else if(c1 == '#')		//判断‘#’和其他符号的优先级
	{
		if(c2 != '(')
		{
			if(c2 == '#')
				c3='=';
			else
				c3='<';
		}
	}

	return c3;		//返回c1和c2比较的优先级结果
}

//Operate为进行二元运算a θb进行运算
double Operate(double a , char theta , double b)
{
	double count;

	switch(theta)
	{
	case '+': count=a+b; break;
	case '-': count=a-b; break;
	case '*': count=a*b; break;
	case '/': count=a/b; break;
	}

	return count;
}

//这两个定义成全局的,因为好多函数要用到
PLStack1 OPTR;
PLStack2 OPND;

//核心算法,算术表达式求值的算符优先算法,OPTR和OPND分别是运算符栈和运算数栈
double EvaluateExpression()
{
	
	
	char c[40];		//这是为了获得重键盘输入的数值
	char x,theta,k;			//x用来后面Pop1存放字符,theta是后面操作字符,k用来存放GetTop取到的字符
	double a=0,b=0,d=0;
	int i=0;

	cout<<"输入表达试!!"<<endl;
	//输入字符并存放到数组中
	gets(c);


	InitStack(OPTR);
	Push1(OPTR , '#');		//栈低是一个‘#’标示已经没有元素了
	InitStack(OPND);

	k=GetTop1(OPTR);		//吧栈顶字符取出
	

	while((c[i] !='#') || k != '#')		//今天先到这吧 2014年4月23日21:04:09	2014年5月1日11:57:03循环有问题!!
	//while(i == -1)
	{
		cout<<k<<"xxxxxxxxxxxxxxxxxx"<<endl;

		if(In(c[i]) != 0)		//判断是否是字符,不是则压入OPND栈
		{
			//cout<<"第 "<<i<<" 个数值是:"<<c[i]<<" 栈顶字符是:"<<k<<endl;
			double j;
			char *p;
			p=&c[i];
			j=atof(p);			//把字符转换成数值
			Push2(OPND , j);		//压入栈
			i++;
		}
		else
		{
			
			switch(Precede(GetTop1(OPTR) , c[i]))		//Precede用来判定它的优先级
			{
			case '<':		//栈顶元素优先权低
				
				Push1(OPTR , c[i]);
				//c = getchar();		//得到下一个字符
				i++;
					
				break;
			case '=':			//脱括号
				Pop1(OPTR , x);
			//	c = getchar();
				i++;
				break;
			case '>':
				theta=Pop1(OPTR , theta);		//取出符号准备计算
				b=Pop2(OPND , b);
				a=Pop2(OPND , a);
				Push2(OPND , Operate(a , theta , b));
				//这里不能写i++,因为这里是要计算,但是还是要用到当前字符和下一个比较2014年5月3日11:17:45
				break;
			}//switch
		}//else

		k=GetTop1(OPTR);	//取出栈顶字符以便循环判断
		
	}//while


	return GetTop2(OPND);
}

void main()
{
	cout<<"结果是:"<<EvaluateExpression()<<endl;;
}


//第三次调试开始 2014年5月1日16:30:20

//决定这个程序写作完全失败!!!!2014年5月1日18:27:54

//重新调试,因为重写了之后,估计知道错误在那了   2014年5月3日11:16:39

//好吧我承认我天真了,还是调试不成功!!!2014年5月3日11:19:12

写了这个之后完全没想法了,赶紧开始新的吧!大哭哭大哭哭,从新开始的事太蛋疼了。。。。。

/*
*	功能:表达式求值
*	时间:2014年5月1日19:09:18
*	作者:cutter_point
*/

	#include <stdio.h>
	#include<stdlib.h>
	#include<iostream>
	#define STACK_INIT_SIZE 10		//用来设置栈的初始大小

	using namespace std;

	//栈的数据结构
	//字符栈
	typedef struct StackChar
	{
		char *base;		//指向栈顶元素的下一个位置
		char *top;		//指向栈底元素
		int stacksize;		//栈当前可使用的最大容量
	}*SCLink;

	//数值栈
	typedef struct StackInt
	{
		int *base;	//指向栈顶元素的下一个位置
		int *top;		//指向栈底元素
		int stacksize;		//栈当前可使用的最大容量
	}*SILink;

	//设置全局变量,定义两个栈
	StackChar OPTR;
	StackInt OPND;
	
/**********************************************************************/
	//栈函数
	void InitStackChar(StackChar &S)		//初始化一个栈
	{
		S.base=(char *)malloc(STACK_INIT_SIZE*sizeof(char));
		S.top=S.base;		//空栈头和尾指针地址相同
		S.stacksize = STACK_INIT_SIZE;		//设置初始大小
	}//InitStackChar

	void InitStackInt(StackInt &S)
	{
		S.base=(int *)malloc(STACK_INIT_SIZE*sizeof(int));
		S.top=S.base;		//空栈头和尾指针地址相同
		S.stacksize = STACK_INIT_SIZE;		//设置初始大小
	}//InitStackInt
/**********************************************************************/
	void PushChar(StackChar &S , char e)		//插入元素e进入栈
	{
		//插入之前先判断空间是否够用
		if(S.top-S.base >= S.stacksize)//栈满了
		{
			S.base=(char *)realloc(S.base , (S.stacksize + STACK_INIT_SIZE)*sizeof(char));
			S.top=S.base+S.stacksize;
			S.stacksize +=STACK_INIT_SIZE;		//刷新数据
		}

		*S.top=e;
		S.top++;

	}//PushChar

	void PushInt(StackInt &S , int e)	
	{
		//插入之前先判断空间是否够用
		if(S.top-S.base >= S.stacksize)//栈满了
		{
			S.base=(int *)realloc(S.base , (S.stacksize + STACK_INIT_SIZE)*sizeof(int));
			S.top=S.base+S.stacksize;
			S.stacksize +=STACK_INIT_SIZE;		//刷新数据

		}

		*S.top=e;
		S.top++;

	}//PushInt
/**********************************************************************/

	char PopChar(StackChar &S)		//删除栈顶元素,取出元素
	{
		char e;

		//如果栈不为空则删除S的栈顶元素,并返回删除的值
		if(S.base != S.top)
		{
			e = *(S.top-1);
			S.top--;
		}

		return e;
	}//PopChar

	int PopInt(StackInt &S)
	{
		int e;

		//如果栈不为空则删除S的栈顶元素,并返回删除的值
		if(S.base != S.top)
		{
			e = *(S.top-1);
			S.top--;
		}

		return e;
	}//PopInt
/**********************************************************************/
	char GetTopChar(StackChar &S)
	{
		char e;

		//若栈不为空,则返回S的栈顶元素
		if(S.base != S.top)
		{
			e = *(S.top-1);		//记住这里S.top指向的是栈顶元素的下一个地址
		}

		return e;
	}//GetTopChar

	int GetTopInt(StackInt &S)
	{
		int e;

		//若栈不为空,则返回S的栈顶元素
		if(S.base != S.top)
		{
			e = *(S.top-1);		//记住这里S.top指向的是栈顶元素的下一个地址
		}

		return e;
	}//GetTopInt
/**********************************************************************/

	//判断函数,是不是字符,不是字符则进入int栈
	int In(char c)
	{
		//判断是运算的字符
		int i=0;

		switch(c)
		{
		case '+': case '-': case '*': case '/':
		case '(': case ')': case '#':
			i++;
			break;
		}

		return i;
	}

	char Precede(char c1 , char c2)	//比较两个字符的优先级		今天就先到这2014年5月1日20:06:36
	{
		char e;			//用来返回判定的结果

		switch(c1)
		{
			case '+': case '-': 
				switch(c2)
				{
					case '+': case '-': case ')': case '#':
						e='>';
					break;
					case '*': case '/': case '(':
						e='<';
					break;
					default:
						printf("\n");
						printf("8888888888888888888888888888888888888888888\n");
						printf("88                                       88\n");
						printf("88                                       88\n");
						printf("88   ①cutter_point制作,盗版不究!!    88\n");
						printf("88                                       88\n");
						printf("88                                       88\n");
						printf("8888888888888888888888888888888888888888888\n");
						break;
				}//switch(c2)  + -
				break;
			case '*': case '/':
				switch(c2)
				{
					case '+': case '-': case '*': case '/': case ')': case '#':
						e='>';
					break;
					case '(':
						e='<';
					break;
					default:
						printf("\n");
						printf("8888888888888888888888888888888888888888888\n");
						printf("88                                       88\n");
						printf("88                                       88\n");
						printf("88   ②cutter_point制作,盗版不究!!    88\n");
						printf("88                                       88\n");
						printf("88                                       88\n");
						printf("8888888888888888888888888888888888888888888\n");
						break;
				}//switch(c2)  *  /
				break;
			case '(':
				switch(c2)
				{
					case '+': case '-': case '*': case '/': case '(':
						e='<';
					break;
					case ')':
						e='=';
					break;
					default:
						printf("\n");
						printf("8888888888888888888888888888888888888888888\n");
						printf("88                                       88\n");
						printf("88                                       88\n");
						printf("88   ③cutter_point制作,盗版不究!!    88\n");
						printf("88                                       88\n");
						printf("88                                       88\n");
						printf("8888888888888888888888888888888888888888888\n");
						break;
				}//switch(c2)  (
				break;
			case ')':
				switch(c2)
				{
					case '+': case '-': case '*': case '/': case ')': case '#':
						e='>';
					break;
					default:
						printf("\n");
						printf("8888888888888888888888888888888888888888888\n");
						printf("88                                       88\n");
						printf("88                                       88\n");
						printf("88   ④可爱cutter_point制作,盗版不究!!88\n");
						printf("88                                       88\n");
						printf("88                                       88\n");
						printf("8888888888888888888888888888888888888888888\n");
						break;
				}//switch(c2)  ')'
				break;
			case '#':
				switch(c2)
				{
					case '+': case '-': case '*': case '/': case '(': case '#':
						e='<';
					break;
					default:
						printf("\n");
						printf("8888888888888888888888888888888888888888888\n");
						printf("88                                       88\n");
						printf("88                                       88\n");
						printf("88   ⑤可爱cutter_point制作,盗版不究!!88\n");
						printf("88                                       88\n");
						printf("88                                       88\n");
						printf("8888888888888888888888888888888888888888888\n");
						break;
				}//switch(c2)  '#'
				break;
			default:
				printf("\n");
				printf("8888888888888888888888888888888888888888888\n");
				printf("88                                       88\n");
				printf("88                                       88\n");
				printf("88      ⑥蛋疼的排版,伤不起!!!!     88\n");
				printf("88                                       88\n");
				printf("88                                       88\n");
				printf("8888888888888888888888888888888888888888888\n");
				break;
		}//switch(c1)

		return e;		//返回比较结果
	}

	int Operate(int a , char theta , int b)		//进行计算,判断应该进行那种计算
	{
		switch(theta)
		{
			case '+':
				return a+b;
			break;
			case '-':
				return a-b;
			break;
			case '*':
				return a*b;
			break;
			case '/':
				return a/b;
			break;
			default:
				printf("程序太难,排版不易,且排且珍惜!\n");
		}
	}
/**********************************************************************/

	int EvaluateExpression()				//表达式求值,关键算法函数
	{
		//算术表达式求值的算符优先算法。设OPTR和OPND分别为运算符栈和运算数栈,
		InitStackChar(OPTR);		//初始化顺序栈
		InitStackInt(OPND);			//同上
		char c[2*STACK_INIT_SIZE],k,theta;		//就是20的空间STACK_INIT_SIZE是 10,k用来接受PopChar消除括号弹出来的,theta用来接受用来计算弹出的符号
		int i=0,j=0,a,b;		//用来计数数组中到了第几个元素了,a,b是后面Pop弹出来计算的,i,j用来指示数组轮转到那了

		PushChar(OPTR , '#');		//栈低先用'#'占据

		printf("输入表达式:");
		gets(c);		//把得到的数据存入到数组中


		printf("表达式是:");
		//输出数组C中的值,看是否已经全部输入
		while(c[j-1] != '#')
		{
			printf("%c",c[j]);
			j++;
		}
		printf("\n");

	//	printf("why you are so 犀利?\n");

		while(c[i] != '#' || GetTopChar(OPTR) != '#')
		{

			if(In(c[i]) == 0)		//不是运算符则进栈
			{
				int j;		//用来存放吧字符转换成的数字
				char *temp;
				temp=&c[i];
				j=(int)atof(temp);		//把字符转换成数值atof(*p)是吧字符转化成浮点型数据
			//	j=c[i]-'0';			//数字与0的距离就是他的数字,ASCII码
			//	printf("%d\n",j);
				PushInt(OPND , j);
				i++;		//取下一个字符
			}
			else
			{
				switch(Precede(GetTopChar(OPTR) , c[i]))
				{
					case '<':
						PushChar(OPTR , c[i]);
						i++;		//取下一个字符
					break;
					case '=':	//消除括号
						k=PopChar(OPTR);
						i++;		//取下一个字符
					break;
					case '>':
						theta=PopChar(OPTR);
						b=PopInt(OPND);
						a=PopInt(OPND);
			//			printf("!!!%d\n",Operate(a,theta,b));
						PushInt(OPND , Operate(a , theta , b));
						break;
				}//switch
			}//else
		}//while

		return GetTopInt(OPND);

	}//EvaluateExpresssion
/**********************************************************************/

	int main( )
	{
		printf("结果是:%d\n",EvaluateExpression());		//基本完成时间2014年5月2日12:14:40 程序待调试
				
		return 0;
	}


//今天调试发现错误点,i++放错位置了,导致while循环老错	2014年5月3日11:04:48
//调试结束,程序完成!
//出自严蔚敏的数据结构算法3_4,表达式求值	2014年5月3日11:10:21

第一次写博客!!

哈哈,我这个人不太会说话,有什么得罪的地方,你来咬我啊偷笑!!

  • 8
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值