字符串表达式的计算(c++版)

一.字符串表达式的解析

      z字符串表达式在栈结构的应用中是一个非常典型的列子,其算法设计思维充分的利用了栈的特性.

     类如: "1+8*9+(4+5)*7" 完成字符串表达式的计算主要分为2个步骤;

    1. 将中缀转化为后缀

              按照(*/+-)的优先级;分别创建2个栈用来贮存数字和符号,从第一个元素遍历,遇到数字进入数字栈,遇到符号进入符号栈,如果入栈符号的优先级小于等于栈顶符号的优先级,则将栈顶元素压入数字栈中,重复上述动作;最后如果符号栈有剩余则全部进入数字栈;

       2.将后缀表达式计算

     遍历全部元素,遇到数字数字压入新栈中,遇到符号将此符号作为前面2个数字的运算符,计算结果压入新栈,直到计算完成

原理图:

                          

二.源代码的实现

        

#include <iostream>
#include <cstdio>
#include <cstring> 
#include <cstdlib>
const int  SIZE = 100; // 栈的初始容量
const int  ADDSIZE = 5; // 栈的单位增加容量
using namespace std;// 命名空间
const int INF = -0xfffffff;// 用于空栈时防止尴尬,返回一个不能读取的地址,让读取的人尴尬;
template <class T>
struct Strack
{
	T *top;// 栈顶的指针
	T *base;// 栈底的指针
	int strackSize;//栈容量
	void init()//栈的初始化
	{
		base = (T *)malloc(SIZE * sizeof(T));//分配内存
		top = base;
		strackSize = SIZE;
	}

	T Top()
	{// 返回栈顶元素
		if (top == base)
			return INF;// 返回尴尬地址
		return *(top - 1);
	}

	bool pop()
	{// 删除栈顶元素
		if (top == base)
			return false;
		top--;
		return true;
	}

	void push(T x)
	{//栈顶插入元素
		if (isPull()) {//如果内存不够重新分配内存
			base = (T *)realloc(base, (strackSize + ADDSIZE)*(sizeof(T)));
			top = base + strackSize;
			strackSize += ADDSIZE;
		}
		*top++ = x;
	}

	bool isEmpty()
	{//判断栈是否为空
		if (top == base)
			return true;
		return false;
	}

	bool isPull()//判满函数
	{
		if (top - base == strackSize)// 一次push一个所以当top - base = strackSize时满
			return true;
		else
			return false;
	}
};

int compareNumber(char x)//用来比较符号的优先级
{
	if (x == '+' || x == '-')
		return 0;
	if (x == '*' || x == '/')
		return 1;
	return -1;
}

void change(char *mid, char *suxfix)//中缀表达式转换为后缀表达式     
{
	int i = 0, len = strlen(mid), mid_index = 0;
	char c;
	Strack<char >intElements;// int数据集
	intElements.init();
	intElements.push('#');// 特殊符号用来区分元素
	while (i < len)
	{
		if (mid[i] == '(')
		{
			intElements.push(mid[i]);
			i++;
		}
		else if (mid[i] == ')')
		{
			while (intElements.Top() != '(')
			{
				suxfix[mid_index++] = intElements.Top();
				suxfix[mid_index++] = ' ';
				intElements.pop();
			}
			intElements.pop();
			i++;
		}
		else if (mid[i] == '+' || mid[i] == '-' || mid[i] == '/' || mid[i] == '*')
		{
			while (compareNumber(intElements.Top()) >= compareNumber(mid[i]))
			{
				suxfix[mid_index++] = intElements.Top();
				suxfix[mid_index++] = ' ';
				intElements.pop();
			}
			intElements.push(mid[i]);
			i++;
		}
		else if (mid[i] >= '0'&&mid[i] <= '9')
		{
			while (mid[i] >= '0'&&mid[i] <= '9')
			{
				suxfix[mid_index++] = mid[i];
				i++;
			}
			suxfix[mid_index++] = ' ';
		}
		else
		{

		}
	}
	while (intElements.Top() != '#') {
		suxfix[mid_index++] = intElements.Top();
		suxfix[mid_index++] = ' ';
		intElements.pop();
	}
	suxfix[mid_index] = 0;
}

double countSuxfix(char *suxfix)//计算后缀表达式   suxfix后缀表达式
{
	int len = strlen(suxfix);
	double x;
	Strack <int >intElements;
	intElements.init();
	int i = 0;
	while (i<len) {
		if (suxfix[i] == ' ')// 用于表达式有效字符集用完跳出循环
		{
			i++;
			continue;
		}
		switch (suxfix[i])
		{
		case '+':
			x = intElements.Top();//根据原理图看
			intElements.pop();
			x = intElements.Top() + x;
			intElements.pop(); i++;
			break;
		case '-':
			x = intElements.Top();
			intElements.pop();
			x = intElements.Top() - x;
			intElements.pop();
			i++;
			break;
		case '*':
			x = intElements.Top();
			intElements.pop();
			x = intElements.Top()*x;
			intElements.pop();
			i++;
			break;
		case '/':
			x = intElements.Top();
			intElements.pop();
			x = intElements.Top() / x;
			intElements.pop();
			i++;
			break;
		default:
		{
			x = 0;
			while (suxfix[i] >= '0'&&suxfix[i] <= '9') {
				x = x * 10 + suxfix[i] - '0';// 连续2个数,第一个*10,以此类推
				i++;
			}
		}
		}

		intElements.push(x);
	}
	return intElements.Top();
}
int main()
{
	char str[1000];
	char newStr[1000];
	scanf("%s", str);
	change(str, newStr);
	cout << newStr << endl;
	cout << countSuxfix(newStr) << endl;
	return 0;
}

--------------------------------------------------------------------------over-----------------------------------------------------------------------------------------

  • 13
    点赞
  • 65
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值