使用链栈的小数和非负数的四则运算(非树形结构)

四则运算

写在前面

学过数据结构的同学都知道中缀和后缀算法,但是记不太清楚了。

本文通过建立两个栈的方法,直接从输入端调用进行运算,方便广大未学过数据结构或是对数据结构不熟悉的同学学习交流。

核心算法源自 《软件技术基础》 ——西安电子科技大学出版社

任务目标

通过 方法实现基本的四则运算。

一个栈用于存放数值,另一个栈用于放置操作符。

通过四则运算练习链栈的创建、访问、置空,和节点元素的插入、删除等操作,并合理运用C++中的函数重载,实现浮点数和字符的操作。

结构框架

在这里插入图片描述
栈结构
在这里插入图片描述核心算法
在这里插入图片描述

算法分析

链栈

栈的构建
创建节点结构
typedef struct node
{
	int flag; //标记位,1为浮点数,2为字符型 
	datatype num;
	chartype sign;
	node* next;
}node;
//栈结构
typedef struct Sqstack
{
	node *Top;
}SqStack;
栈的声明
//构造一个空栈 
void InitStack(SqStack *& S);
//置空栈
void SetNull(SqStack *S); 
//判断栈空
int Empty(SqStack*S);
//函数重载
//出栈 根据格式返回需要的元素
void Pop(SqStack *S,datatype &e);
void Pop(SqStack *S,chartype &e);
//入栈 根据格式返回需要的元素
void Push(SqStack *S,datatype n);
void Push(SqStack *S,chartype s);
//获得栈顶元素 根据格式返回需要的元素
void GetTop(SqStack *S,datatype &e);
void GetTop(SqStack *S,chartype &e);
栈的基本功能
//构造一个空栈 
void InitStack(SqStack *& S)
{
	S = (SqStack*)malloc(sizeof(SqStack));
	S->Top = NULL;
}

//置空栈
void SetNull(SqStack *S)
{
	node* p = NULL;
	while(S->Top != NULL)
	{
		p = S->Top;
		S->Top = p->next;
		free(p);p = NULL;
	} 
	cout<<"置空成功"<<endl;
}

//判断栈空,空返回1 
int Empty(SqStack*S)
{
	if(S->Top<=0) return 1;
	else return 0;
 } 

//入栈 
void Push(SqStack *S,datatype n)
{
	node *p = (node*)malloc(sizeof(node));
	if(p != NULL)
	{
		p->flag = 1;
		p->num = n;
		p->next = S->Top;
		S->Top = p;
		cout<<"Num入栈成功:"<<p->num<<endl;
	}
	else 
		cout<<"Error"<<endl;
}
void Push(SqStack *S,chartype s)
{
	node *p = (node*)malloc(sizeof(node));
	if(p != NULL)
	{
		p->flag = 2;
		p->sign = s;
		p->next = S->Top;
		S->Top = p;
		cout<<"Sign入栈成功:"<<p->sign<<endl;
	}
	else 
		cout<<"Error"<<endl;
}

//出栈 
void Pop(SqStack *S,datatype &e)
{
	if(S->Top != NULL)
	{
		node* p = S->Top;
		e = p->num;
		S->Top = p->next;
		free(p);
		cout<<"出栈成功: "<<e<<endl;
	}
	else {}
}
void Pop(SqStack *S,chartype &e)
{
	if(S->Top != NULL)
	{
		node* p = S->Top;
		e = p->sign;
		S->Top = p->next;
		free(p);
		cout<<"出栈成功: "<<e<<endl;
	}
	else {}
}

//获得栈顶元素 
void GetTop(SqStack *S,chartype &e)
{
	if(S->Top != NULL)
		e = S->Top->sign;
	else {}
}
void GetTop(SqStack *S,datatype &e)
{
	if(S->Top != NULL)
		e = S->Top->num;
	else {}
}

四则运算

函数声明
//判断是否为字符型,是返回1,否返回0 
int CharOrNot(char ch); 
//输入表达式保存 
void GetExpression(SqStack *&S);
//输入输出对换 
void ReturnStack(SqStack *&S);
//四则运算 
datatype EvaluateExpression(SqStack *C);
//自带输入的四则运算 
datatype EvaluateExpression();
//判断优先级 
chartype Precede(chartype a,chartype b);
//对相关运算进行封装,返回运算结果 
datatype Operate(datatype a,chartype b,datatype c);
读取算数表达式
//获取表达式 
void GetExpression(SqStack *&S)
{
	cout<<"请输入运算代数式:";
	char ch=0;
	ch = getchar();
	while (ch !='\n') 
	{
		if(CharOrNot(ch))//为字符 
		{
			Push(S,ch);
			ch = getchar();
		}
		else 
		{
			datatype k=1;
			datatype m=datatype(ch)-48;
			ch = getchar();
			while(ch!='.' && !CharOrNot(ch))
			{
				m=m*10+int(ch)-48;
				ch = getchar();
			}
			if(ch=='.') ch=getchar();
			while(!CharOrNot(ch))	
			{
				k=0.1*k;
				m=m+k*(int(ch)-48);
				ch = getchar();
			}	
			Push(S,m);
		}
	}
}
转换算数式顺序-出栈进栈

按照输入顺序输出,方便进行运算

//变换顺序 
void ReturnStack(SqStack *&S)
{
	SqStack *Q;node *p;
	InitStack(Q);
	datatype a;chartype b;
	
	while(S->Top!=NULL)
	{
		p=S->Top;
		S->Top = p->next;
		p->next = Q->Top; 
		Q->Top=p;
	}
	S->Top = Q->Top;
	Q->Top = NULL;
	free(Q);
	cout<<"转变完成"<<endl;
}
判断优先级
//判断优先级 
chartype Precede(chartype a,chartype b)
{
	int m,n;
	switch(a)
	{
		case '#': m=0;break;
		case '-':
		case '+': m=2;break;
		case '*':
		case '/': m=3;break;
		case '(': m=1;break;
		//default
		//case')': m=3;
	}
	switch(b)
	{
		case '#': n=0;break;
		case '-':
		case '+': n=2;break;
		case '*':
		case '/': n=3;break;
		case '(': n=4;break;
		case ')': n=1;break;
		//default
	}

	if(m<n)
		a='<';
	else if(m==n && m == 1)//脱括号 
		a='=';
	else if(m==n &&m != 0 && m!= 1 || m>n)
		a='>';
		
	return a;
}
操作符运算
datatype Operate(datatype a,chartype b,datatype c)
{
	switch(b)
	{
		case'+':	return a+c;break;
		case'-':	return c-a;break;
		case'*':	return a*c;break;
		case'/':	return c/a;break;
	}
}
四则运算函数
datatype EvaluateExpression(SqStack *C)
{
	SqStack *S,*Q;node *p;
	InitStack(S);InitStack(Q);
	Push(Q,'#'); //作为结束判断的标志 
	chartype b='!';datatype a;datatype c; 
	//当最后一个和第一个元素都为#时结束 
	while(p->sign!='#' || b!='#')
	{
		ifcp->flag == 1)//flag = 1 为数字 
		{
			Push(S,p->num);p=p->next;//进入数字栈 
        }
		else if(p->flag == 2)  //为字符 
		{
			GetTop(Q,b);
			//通过switch判断需要做的操作 
			switch(Precede(b,p->sign)){
			case'<'://栈顶符号优先级小于当前符号 
					Push(Q,p->sign);//对当前进行进栈操作 
					p=p->next;//p指向下一个节点 
					break;
			case'='://脱括号 
					Pop(Q,b);//出栈 
					p=p->next;//p指向下一个节点 
					break;
			case'>':// 栈顶符号优先级大于当前符号 
					Pop(Q,b);//出栈操作符 
					Pop(S,a);//得到第二个数字
					Pop(S,c);//得到第一个数字
					Push(S,Operate(a,b,c));//将运算结c果进栈 
					break;
			}
		}
		GetTop(Q,b);//更新 b 为栈顶元素符号,方便判断 
	}
	GetTop(S,a);//结束循环,返回数字栈结果 
	SetNull(S);SetNull(Q);//置空 
	free(S);free(Q);free(p);//释放栈格式 
	
	return a;//返回结果 
} 

附:自带读取功能的四则算法

无需读取算数表达式的操作,可直接调用

本文栈相关操作与之匹配

提供不同的思路方法

 //无需读取字符串算法 
/*datatype EvaluateExpression()
{
	SqStack *S,*Q;
	InitStack(S);InitStack(Q);
	Push(S,'#');Push(Q,'#'); 
	chartype b; chartype d; datatype a;datatype c; 
	cout<<"请输入运算代数式:";
	chartype ch=getchar();
	while(ch!='#' || b!='#')
	{
		if(!CharOrNot(ch))
		{
			a=datatype(ch);
			Push(S,a-48);
			ch=getchar();
		}
		else 
		{
			d = chartype(ch);GetTop(Q,b);
			switch(Precede(b,d)){
			case'<':
					Push(Q,ch);ch=getchar();break;
			case'=':
					Pop(Q,b);ch=getchar();break;
			case'>':
					Pop(Q,b);//操作符 
					Pop(S,a);//第一个数字
					Pop(S,c);//第二个数字
					Push(S,Operate(a,b,c));
					break;
			}
		}
		GetTop(Q,b); 
	}
	GetTop(S,a);
	SetNull(S);SetNull(Q);
	free(S);free(Q);
	
	return a;
 } 

结果分析

基本的四则运算

带括号的运算

小数运算

在这里插入图片描述

负数运算

写道这里已经满足了上机需求,并且花费了许多时间用于调试和理解算法。之后有时间会添加上这一部分。

完整代码

main.cpp

#include "func.h"
int main()
{
	SqStack *S;
	InitStack(S);
	GetExpression(S);
	ReturnStack(S);
	datatype a;
	a = EvaluateExpression(S);
	cout<<"运算结果: "<<a<<endl;
	SetNull(S);
	free(S);
	return 0;
}

func.h


#include<iostream>
#include <stdlib.h>
using namespace std;
typedef float datatype;
typedef char chartype;
#define MaxSize 30

//定义栈格式 
typedef struct node
{
	int flag; //标记位,1为浮点数,2为字符型 
	datatype num;
	chartype sign;
	node* next;
}node;

typedef struct Sqstack
{
	node *Top;
}SqStack;

//构造一个空栈 
void InitStack(SqStack *& S);

//置空栈
void SetNull(SqStack *S); 

//判断栈空
int Empty(SqStack*S);

//出栈 
void Pop(SqStack *S,datatype &e);
void Pop(SqStack *S,chartype &e);
//入栈 
void Push(SqStack *S,datatype n);
void Push(SqStack *S,chartype s);
//
void GetTop(SqStack *S,datatype &e);
void GetTop(SqStack *S,chartype &e);
//判断是否为字符型,是返回1,否返回0 
int CharOrNot(char ch); 
//输入表达式保存 
void GetExpression(SqStack *&S);
//输入输出对换 
void ReturnStack(SqStack *&S);
//四则运算 
datatype EvaluateExpression(SqStack *C);
//自带输入的四则运算 
datatype EvaluateExpression();
//判断优先级 
chartype Precede(chartype a,chartype b);
//对相关运算进行封装,返回运算结果 
datatype Operate(datatype a,chartype b,datatype c);

func.cpp

#include "func.h" 
//构造一个空栈 
void InitStack(SqStack *& S)
{
	S = (SqStack*)malloc(sizeof(SqStack));
	S->Top = NULL;
}

//置空栈
void SetNull(SqStack *S)
{
	node* p = NULL;
	while(S->Top != NULL)
	{
		p = S->Top;
		S->Top = p->next;
		free(p);p = NULL;
	} 
	cout<<"置空成功"<<endl;
}

//判断栈空,空返回1 
int Empty(SqStack*S)
{
	if(S->Top<=0) return 1;
	else return 0;
 } 

//入栈 
void Push(SqStack *S,datatype n)
{
	node *p = (node*)malloc(sizeof(node));
	if(p != NULL)
	{
		p->flag = 1;
		p->num = n;
		p->next = S->Top;
		S->Top = p;
		//cout<<"Num入栈成功:"<<p->num<<endl;
	}
	else 
		cout<<"Error"<<endl;
}
//入栈 
void Push(SqStack *S,chartype s)
{
	node *p = (node*)malloc(sizeof(node));
	if(p != NULL)
	{
		p->flag = 2;
		p->sign = s;
		p->next = S->Top;
		S->Top = p;
		//cout<<"Sign入栈成功:"<<p->sign<<endl;
	}
	else 
		cout<<"Error"<<endl;
}

//出栈 
void Pop(SqStack *S,datatype &e)
{
	if(S->Top != NULL)
	{
		node* p = S->Top;
		e = p->num;
		S->Top = p->next;
		free(p);
		//cout<<"出栈成功: "<<e<<endl;
	}
	else {}
}
void Pop(SqStack *S,chartype &e)
{
	if(S->Top != NULL)
	{
		node* p = S->Top;
		e = p->sign;
		S->Top = p->next;
		free(p);
		//cout<<"出栈成功: "<<e<<endl;
	}
	else {}
}

//获得栈顶元素 
void GetTop(SqStack *S,chartype &e)
{
	if(S->Top != NULL)
		e = S->Top->sign;
	else {}
}
void GetTop(SqStack *S,datatype &e)
{
	if(S->Top != NULL)
		e = S->Top->num;
	else {}
}

//判断运算符 为真返回1
int CharOrNot(char ch)
{
	if(ch!='+'&&ch!='-'&&ch!='*'&&ch!='/'&&ch!='('&&ch!=')'&&ch!='#')
	return 0;
	else return 1;
} 
//获取表达式 
void GetExpression(SqStack *&S)
{
	cout<<"请输入运算代数式:";
	char ch=0;
	ch = getchar();
	while (ch !='\n') 
	{
		if(CharOrNot(ch))//为字符 
		{
			Push(S,ch);
			ch = getchar();
		}
		else 
		{
			datatype k=1;
			datatype m=datatype(ch)-48;
			ch = getchar();
			while(ch!='.' && !CharOrNot(ch))
			{
				m=m*10+int(ch)-48;
				ch = getchar();
			}
			if(ch=='.') ch=getchar();
			while(!CharOrNot(ch))	
			{
				k=0.1*k;
				m=m+k*(int(ch)-48);
				ch = getchar();
			}	
			Push(S,m);
		}
	}
	cout<<"输入完毕"<<endl; 
}

//变换顺序 
void ReturnStack(SqStack *&S)
{
	SqStack *Q;node *p;
	InitStack(Q);
	datatype a;chartype b;
	
	while(S->Top!=NULL)
	{
		p=S->Top;
		S->Top = p->next;
		p->next = Q->Top; 
		Q->Top=p;
	}
	S->Top = Q->Top;
	Q->Top = NULL;
	free(Q);
	cout<<"转变完成"<<endl;
}

//输入栈 处理 
datatype EvaluateExpression(SqStack *C)
{
	SqStack *S,*Q;node *p;
	InitStack(S);InitStack(Q);
	Push(Q,'#'); //作为结束判断的标志 
	chartype b='!';datatype a;datatype c; 
	//当最后一个和第一个元素都为#时结束 
	while(p->sign!='#' || b!='#')
	{
		if(p->flag == 1)//flag = 1 为数字 
		{
			Push(S,p->num);p=p->next;//进入数字栈 
		}
		else if(p->flag == 2)  //为字符 
		{
			GetTop(Q,b);
			//通过switch判断需要做的操作 
			switch(Precede(b,p->sign)){
			case'<'://栈顶符号优先级小于当前符号 
					Push(Q,p->sign);//对当前进行进栈操作 
					p=p->next;//p指向下一个节点 
					break;
			case'='://脱括号 
					Pop(Q,b);//出栈 
					p=p->next;//p指向下一个节点 
					break;
			case'>':// 栈顶符号优先级大于当前符号 
					Pop(Q,b);//出栈操作符 
					Pop(S,a);//得到第二个数字
					Pop(S,c);//得到第一个数字
					Push(S,Operate(a,b,c));//将运算结果进栈 
					break;
				}
		}
		GetTop(Q,b);//更新 b 为栈顶元素符号,方便判断 
	}
	GetTop(S,a);//结束循环,返回数字栈结果 
	SetNull(S);SetNull(Q);//置空 
	free(S);free(Q);free(p);//释放栈格式 
	
	return a;//返回结果 
} 
 
 //无需读取字符串算法 
/*datatype EvaluateExpression()
{
	SqStack *S,*Q;
	InitStack(S);InitStack(Q);
	Push(S,'#');Push(Q,'#'); 
	chartype b; chartype d; datatype a;datatype c; 
	cout<<"请输入运算代数式:";
	chartype ch=getchar();
	while(ch!='#' || b!='#')
	{
		if(!CharOrNot(ch))
		{
			a=datatype(ch);
			Push(S,a-48);
			ch=getchar();
		}
		else 
		{
			d = chartype(ch);GetTop(Q,b);
			switch(Precede(b,d)){
			case'<':
					Push(Q,ch);ch=getchar();break;
			case'=':
					Pop(Q,b);ch=getchar();break;
			case'>':
					Pop(Q,b);//操作符 
					Pop(S,a);//第一个数字
					Pop(S,c);//第二个数字
					Push(S,Operate(a,b,c));
					break;
			}
		}
		GetTop(Q,b); 
	}
	GetTop(S,a);
	SetNull(S);SetNull(Q);
	free(S);free(Q);
	
	return a;
 } 
*/

//判断优先级 
chartype Precede(chartype a,chartype b)
{
	int m,n;
	switch(a)
	{
		case '#': m=0;break;
		case '-':
		case '+': m=2;break;
		case '*':
		case '/': m=3;break;
		case '(': m=1;break;
		//default
		//case')': m=3;
	}
	switch(b)
	{
		case '#': n=0;break;
		case '-':
		case '+': n=2;break;
		case '*':
		case '/': n=3;break;
		case '(': n=4;break;
		case ')': n=1;break;
		//default
	}

	if(m<n)
		a='<';
	else if(m==n && m == 1)//脱括号 
		a='=';
	else if(m==n &&m != 0 && m!= 1 || m>n)
		a='>';
		
	return a;
}

datatype Operate(datatype a,chartype b,datatype c)
{
	switch(b)
	{
		case'+':	return a+c;break;
		case'-':	return c-a;break;
		case'*':	return a*c;break;
		case'/':	return c/a;break;
	}
	
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值