数据结构之栈(后缀表达式转中缀表达式)

**正文实现的功能:**把像(1+2*3)*2-4#的表达式算出来
参照逻辑:小甲鱼的数据结构、大话数据结构
整合了一些功能

1、栈表的初始化
#include <iostream>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>

#define STACK_INIT_SIZE 20
#define STACKINCREMENT  10
#define MAXBUFFER       10
using namespace std;


typedef double ElemType;
//栈的结构体
typedef struct
{
	ElemType *base;
	ElemType *top;
	int stackSize;
}sqStack;    

//初始化栈
void InitStack(sqStack *s)
{
	s->base = (ElemType *)malloc(STACK_INIT_SIZE * sizeof(ElemType));
	if (!s->base)
		exit(0);

	s->top = s->base;
	s->stackSize = STACK_INIT_SIZE;
}

//压栈
void Push(sqStack *s, ElemType e)
{
	// 栈满,追加空间,鱼油必须懂!
	if (s->top - s->base >= s->stackSize)
	{
		s->base = (ElemType *)realloc(s->base, (s->stackSize + STACKINCREMENT) * sizeof(ElemType));
		if (!s->base)
			exit(0);

		//s->top = s->base + s->stackSize; 
		//第一时间并没有添加如此多的元素,所以没必要
		s->stackSize = s->stackSize + STACKINCREMENT;
	}

	*(s->top) = e;      // 存放数据
	s->top++;
}
//出栈
void Pop(sqStack *s, ElemType *e)
{
	if (s->top == s->base)
		return;

	//*e = *--(s->top);   // 将栈顶元素弹出并修改栈顶指针
	*e =* (s->top-1);
	s->top--;
}
//栈元素的长度
int StackLen(sqStack s)
{
	return (s.top - s.base);
}
//遍历栈
void StackTraverse(sqStack s)
{
	while (s.base != s.top)
	{
		s.top--;
		printf("%.1f\n", *s.top);
	}
}
2、后缀表达式
/*
  返回值:计算之后的值
  参数1:后缀表达式的字符串
  参数2:栈表,可以用局部变量
*/
double GetValue(char* cSrc,sqStack s)  
{
	int j = 0; char a[10];int i=0;
	ElemType c, d;

	printf("请输入你的表达式\n");
	while (cSrc[j] != '#')   //判断结束符
	{
		while (int(cSrc[j]) <= 57 && int(cSrc[j]) >= 48)
		{
			a[i] = cSrc[j];
			a[i + 1] = '\0';  //c++中字符串以字符‘\0’结尾,所以每个字符串都有额外一个字符的开销。
			i++;
			if (i > 10)
				printf("输入长度超限");
			j++;
			if (cSrc[j] == ' ') //判断下一个是否是 空格(分离出数字)
			{
				Push(&s, atof(a));
				printf("传入的数据\n");
				StackTraverse(s);
				i = 0;
				break;
			}
		}
		switch (cSrc[j])
		{
		case('+'):
			Pop(&s, &c);
			Pop(&s, &d);
			Push(&s, c + d);
			break;
		case('-'):
			Pop(&s, &c);
			Pop(&s, &d);
			Push(&s, d - c);
			break;
		case('*'):
			Pop(&s, &c);
			Pop(&s, &d);
			Push(&s, d * c);
			break;
		case('/'):
			Pop(&s, &c);
			Pop(&s, &d);
			if (c == 0)
			{
				printf("除数已经为0");
				break;
			}
			Push(&s, d / c);
			break;
		default:
			break;
		}
		j++;
	}
	Pop(&s, &c);
	return c;
}
3、中缀表达式 转 后缀表达式
//返回值 可以用全局变量,也可以传一个字符指针作为参数
char* GetInfix(char* ch)
{
	char s[100]; int i = 0;int j=0;
	sqStack p; ElemType e;


	InitStack(&p); //初始化栈
	while (ch[i] != '#')
	{
		while (ch[i] >= '0' && ch[i] <= '9')
		{
			s[j] = ch[i];
			j++;
			i++;
			if (ch[i]<'0' || ch[i]>'9')
			{
				s[j] = ' ';
				j++;
			}
		}
//并列条件,先判断谁都行
		if (')'==ch[i])
		{ 
			printf("存了多少个\n");
			StackTraverse(p);
  			Pop(&p,&e);
			while ('(' != char(e))
			{
				s[j] = char(e);
				j++;
				Pop(&p,&e);
			}
		}
		else if ('+' == ch[i] || '-' == ch[i])  //权限最低,权限高的弹出
		{
			if (!StackLen(p)) //如果为空压栈
			{
				Push(&p, ch[i]);
			}
			else {
				do {
					Pop(&p, &e);          //弹出元素
					if ('(' == char(e))
					{
						Push(&p, e);//再次压入栈,为了上面的判断
					}
					else                 //之前的加减乘除弹出来
					{
						s[j] = char(e);
						j++;
					}
				
				} while(StackLen(p) && '('!= char(e));
				Push(&p, ch[i]);
			}
		}
		else if ('*' == ch[i] || '/' == ch[i] || '(' == ch[i])
		{
			Push(&p, ch[i]);
		}
		else if ('#' == ch[i])
		{
			Pop(&p,&e);
			s[j] = char(e);
			j++;
			s[j] = '#';
			break;
		}
		else
		{
			printf("\n出错:输入格式错误!\n");
			break;
		}
		i++;
	}
	return t;	
}
4、主程序实现逻辑
int main()
{
	sqStack s; char e;
	ElemType c, d;
	char a[10];
	char chr;
	int i = 0;
	char ct[100];

	InitStack(&s);
	printf("请输入你的表达式");
	int k = 0;
	scanf("%c", &chr);
	while (chr != '#')
	{
		ct[k] = chr;
		k++;
		scanf("%c", &chr);
	}
	ct[k] = '#';
	k++;

	strcpy(ct,GetInfix(ct));//必须这样
	double t= GetValue(ct, s);

	printf("已经运算完毕%.1f\n", t);
	getchar();
	return 0;
}
5、遇到的问题

1、返回值用 char*,只要不用strcpy得到的值便是乱码;
https://zhidao.baidu.com/question/14732048.html
解决方案:(1)将返回值作为形参传入(2) 用strcpy函数 (3)全局变量
2、注意细节逻辑

完整代码:链接:https://pan.baidu.com/s/1cTwVbTV07xHCcVASRgrwtA
提取码:mx17

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
后缀表达式中缀表达式的算法是基于的。具体实现步骤如下: 1. 从左到右扫描后缀表达式的每一个字符。 2. 如果是数字或者变量,则将其压入中。 3. 如果是运算符,则从中弹出两个元素,拼接成中缀表达式的一部分,并将拼接后的表达式压入中。 4. 扫描完整个后缀表达式后,中只剩下一个元素,即为中缀表达式。 具体的实现代码如下: ``` #include <iostream> #include <stack> #include <string> using namespace std; bool isOperator(char c) { return c == '+' || c == '-' || c == '*' || c == '/'; } string postfixToInfix(string postfix) { stack<string> s; for (char c : postfix) { if (isOperator(c)) { string op1 = s.top(); s.pop(); string op2 = s.top(); s.pop(); s.push("(" + op2 + " " + c + " " + op1 + ")"); } else { s.push(string(1, c)); } } return s.top(); } int main() { string postfix = "23+4*"; string infix = postfixToInfix(postfix); cout << infix << endl; return 0; } ``` 上述代码中,isOperator() 函数用于判断一个字符是否为运算符。postfixToInfix() 函数实现了将后缀表达式化为中缀表达式的算法。在函数中,定义了一个 s 用于保存中间结果。对于每一个字符: - 如果是运算符,则从中弹出两个元素,并将它们拼接成中缀表达式的一部分,然后将拼接后的表达式压入中; - 如果是数字或者变量,则将其压入中。 最终,中只剩下一个元素,即为中缀表达式

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值