数据结构06-链表队列

代码如下:

#include"DataStructure.hpp"
#include<iostream>
using namespace std;

/**
  * @brief  显示两个运算符的优先级别
  * @param  运算符1,表达式中前面的运算符
  * @param  运算符2,表达式中后面的运算符
  * @retval 返回相对优先级别,op1>op2:1,op1<op2:-1,op1=op2:0
  */

int op_cmp(char op1, char op2)  
{
	int val = 2;
	switch (op1)
	{
	case '+':
	{
		switch (op2)
		{
		case '+':val = 1; break;
		case '-':val = 1; break;
		case '*':val = -1; break;
		case '/':val = -1; break;
		case '(':val = -1; break;
		case ')':val = 1; break;
		case '#':val = 1; break;
		default:
			break;
		}
	}break;
	case '-':
	{
		switch (op2)
		{
		case '+':val = 1; break;
		case '-':val = 1; break;
		case '*':val = -1; break;
		case '/':val = -1; break;
		case '(':val = -1; break;
		case ')':val = 1; break;
		case '#':val = 1; break;
		default:
			break;
		}
	}break;
	case '*':
	{
		switch (op2)
		{
		case '+':val = 1; break;
		case '-':val = 1;break;
		case '*':val = 1;break;
		case '/':val = 1;break;
		case '(':val = -1;break;
		case ')':val = 1;break;
		case '#':val = 1;break;
		default:
			break;
		}
	}
	case '/':
	{
		switch (op2)
		{
		case '+':val = 1; break;
		case '-':val = 1; break;
		case '*':val = 1; break;
		case '/':val = 1; break;
		case '(':val = -1; break;
		case ')':val = 1; break;
		case '#':val = 1; break;
		default:
			break;
		}
	}break;
	case '(':
	{
		switch (op2)
		{
		case '+':val = -1; break;
		case '-':val = -1; break;
		case '*':val = -1; break;
		case '/':val = -1; break;
		case '(':val = -1; break;
		case ')':val = 0; break;
		default:
			break;
		}
	}break;
	case ')':
	{
		switch (op2)
		{
		case '+':val = 1;break;
		case '-':val = 1;break;
		case '*':val = 1;break;
		case '/':val = 1;break;
		case '(':val = 1;break;
		case '#':val = 1;break;
		default:
			break;
		}
	}
	case '#':
	{
		switch (op2)
		{
		case '+':val = -1; break;
		case '-':val = -1; break;
		case '*':val = -1; break;
		case '/':val = -1; break;
		case '(':val = -1; break;
		case '#':val = 0; break;
		default:
			break;
		}
	}break;
	default:
		break;
	}
	return val;
}
/**
  * @brief  计算一个只含一个操作符的算式
  * @param  前一个操作数
  * @param  后一个操作数
  * @param  操作符
  * @retval 返回结果
  */

int Caculate(int pre, int next, char op)
{
	int Retval;
	switch (op)
	{
	case '+':
		Retval = pre + next;
		break;
	case '-':
		Retval = pre - next;
		break;
	case '*':
		Retval = pre * next;
		break;
	case '/':
		Retval = pre / next;
		break;
	default:
		break;
	}
	return Retval;
}

/**
  * @brief  表达式求解的主要函数。
  * @param  表达式以字符串的形式传入
  * @retval 返回最终结果
  */


int GetExpVal(string exp)
{
	int val = 65535;
	Stack<char> optr;
	Stack<int>opnd;
	optr.push('#');
	int i = 0;
	while (exp[i] != '#'||optr.gettopdata()!='#')
	{
		if (exp[i] <= '9' && exp[i] >= '0')
		{
			opnd.push(exp[i] - '0');
			i++;
		}
		else
		{
			int rel = op_cmp(optr.gettopdata(), exp[i]);
			if (rel == 0)
			{
				optr.pop();
				i++;
			}
			else if (rel == 1)
			{
				char op;
				int pre, next;
				op = optr.pop();
				next = opnd.pop();
				pre = opnd.pop();
				int tempval = Caculate(pre, next, op);
				opnd.push(tempval);
			}
			else if (rel == -1)
			{
				optr.push(exp[i]);
				i++;
			}
		}
	}
	val = opnd.gettopdata();
	return val;
}

int main()
{
	cout <<"1+2*(3-4)="<< GetExpVal("1+2*(3-4)#") << endl;
	cout << "1*(5-4)/2=" << GetExpVal("1*(5-4)/2#") << endl;
	return 0;
}

其中的栈操作代码如下:

#pragma once
#include<iostream>
using namespace std;
#define MaxSize 100

//初始化,压栈,入栈

template<class T>
class Stack {
private:
	int top;
	T data[MaxSize];
public:
	Stack();
	T pop();
	void push(T);
	void PrintStack();
	T gettopdata();
};
#include"DataStructure.hpp"
template<class T>
Stack<T>::Stack()
{
	this->top = -1;
}
template<class T>
void Stack<T>::PrintStack()
{
	int index = this->top;
	if (index == -1)
	{
		cout << "栈空!" << " ";
	}
	while (index >= 0)
	{
		cout << this->data[index] << " ";
		index--;
	}
}
template<class T>
void Stack<T>::push(T data)
{
	if (this->top + 1 == MaxSize)
	{
		cout << "栈满" << " ";
		return;
	}
	this->data[++this->top] = data;
}
template<class T>
T Stack<T>::pop()
{
	if (this->top < 0)
	{
		cout << "栈空" <<" ";
		return -1;
	}
	this->top--;
	return this->data[this->top + 1];
}
template<class T>
T Stack<T>::gettopdata()
{
	return this->data[top];
}
void Stacktest()
{
	Stack<int> s;
	s.push(10);
	s.push(11);
	s.push(12);
	s.push(13);
	s.PrintStack();
}


我使用的表达式求值方法貌似与逆波兰求值法有一些不同,是按照严蔚敏教材上的方法做的,讲解如下:

首先我们了解一下写代码的思路,我们知道,在我们自己进行四则运算时,主要遵循以下三条法则:
1、先乘除后加减
2、从左往右算
3、先算括号内,再算括号外的。
于是我们得到如下表:
摘自数据结构一书

注意,我们为了方便,在算术中引入了‘#’符号作为标识符,以便操作。并且,由法则2,我们可以得到在有连续两个操作符相等的情况下,前一个操作符的优先级更大。
我们定义好优先级后,就会想到如何实现求解表达式求值,这里我们使用了两个栈。一个是操作数栈,一个是操作符栈,为了操作方便,我们先在操作符压入一个‘#’,同时,我们也要在表达式后缀加一个‘#’。如代码所示

in GetExpVal function()
optr.push('#');
in main funtion();
cout <<"1+2*(3-4)="<< GetExpVal("1+2*(3-4)#") << endl;

这里我们用一个循环读取字符串,进入循环终止条件为当读到的字符是‘#’并且操作符栈中也只剩下‘#’时(这时候我们将所以的表达式都读取了并且我们把所有的操作的执行了),循环结束。
在循环中,我们先判断是否为数字,如果是数字,则压入操作数栈,如果是操作符,则有三种情况:
第一种情况是栈顶的操作符优先级小于读入的操作符,此时将读入的操作符压栈。(优先级低的后执行,根据栈的特性,肯定是越靠近栈顶的操作越先被执行,所以优先级大越大的,在越上面)。

第二种情况则是相等,从我们的优先级图中,我们可以知道,相等只有两种情况:‘#’–‘#’和‘(’–‘)’,如果是‘#’和‘#’,证明表达式已经结束,即符合循环终止条件,所以只有可能是‘(’–‘)’,啥时候会出现左右括号是连续的?当然是括号中的运算已经完成了,所有操作符都出栈了,那么此时我们就不将读入的字符(即‘)’)入栈,而是将栈顶元素‘(’出栈,这样就完成了一次括号内的运算。

第三种情况则是大于,根据优先级高的先执行,那么此时我们的栈顶元素就是优先级最高的操作符,所以应该执行运算操作,所以我们此时应该将操作数的前两个元素出栈,操作符中的前一个元素出栈,进入计算函数,并将计算后的结果压入操作数栈中(我们在手动计算表达式时,也会将中间值再次代入到表达式中)。

如此,直到读取完字符串中的元素并且将操作符栈的元素都执行了后,就结束循环。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值