数据结构_2_表达式的计算



使用的数据结构书本是 殷人昆 主编的,

为了熟悉课本的代码就边写边打边改

1.自己手写栈

#pragma once
#include<iostream>
using namespace std;

template<class T>
struct LinkedNode {
	T x;
	LinkedNode<T> *next;
};

template<class T>
class LinkedStack
{
public:
	LinkedStack() :top(NULL) {}
	~LinkedStack(){ makeEmpty(); };
	void makeEmpty();
	void push(T& x);
	bool pop(T& x);
	bool getTop(T& x)const;
	bool IsEmpty()const { return(top == NULL) ? true : false; }
	int getSize()const;

private:
	LinkedNode<T>* top;
};

template<class T>
void LinkedStack<T>::makeEmpty() {
	LinkedNode<T> *p;
	while (top != NULL)
	{
		p = top;
		top = top->next;
		delete p; 
	}
};

template<class T>
void LinkedStack<T>::push(T& x)
{
	LinkedNode<T>* temp = new LinkedNode<T>;
	temp->x = x;
	temp->next = top;
	top = temp;
}

template<class T>
bool LinkedStack<T>::pop(T& x)
{
	if (IsEmpty() == true)
		return false;
	
	LinkedNode<T>* temp = top;
	top = top->next;
	x = temp->x;
	delete temp;
	return true;
}

template<class T>
bool LinkedStack<T>::getTop(T& x)const
{
	if (IsEmpty() == true)
		return false;

	x = top->x;
	return true;
}

template<class T>
int LinkedStack<T>::getSize() const
{
	int size = 0;
	LinkedNode<T>* temp = top;
	while (top != NUL)
	{
		top = top->next;
		size++;
	}
	return size;
}
2.Calculator类

#pragma once
#include<math.h>
#include"stack.h"
#include<string>
#include<iostream>

using namespace std;

class Calculator {
public:
	Calculator() {};
	void Run(string str);
	void Clear();
	LinkedStack<double> s;
private:
	
	void addOperand(double value);//进操作数栈队
	bool get2Operands(double& left, double& right);//从栈中退出两个操作数
	void DoOperator(char op);//形成运算指令,进行计算
};

void Calculator::DoOperator(char op) {
	//取两个操作数,根据两个操作数,根据操作符op形成运算指令并计算
	double left, right, value;
	int result;
	result = get2Operands(left, right);
	if (result == true)
	{
		//如果取两个操作数成功,则计算并出栈
		switch (op) {
		case'+':value = left + right;
			s.push(value);
			break;//plus
		case'-':value = left - right;
			s.push(value);
			break;//sub
		case'*':value = left*right;
			s.push(value);
			break;
		case'/':if (right == 0.0) {
			cerr << "Divide by 0!" << endl;
			Clear();
			}else{ value = left / right; }

		break;
		}
	}
	else Clear();//取操作数出错,出栈
}

bool Calculator::get2Operands(double& left, double& right) {
	//取出两个操作数
	if(s.IsEmpty()==true)
	{
		cerr << "缺少右操作数" << endl;
		return false;
	}
	s.pop(right);

	if (s.IsEmpty() == true)
	{
		cerr << "缺少左操作数" << endl;
		return false;
	}
	s.pop(left);
	return true;
}

void Calculator::addOperand(double value) {
	//将操作数的value进操作数栈
	s.push(value);
}

void Calculator::Run(string str) {
	char ch;
	double newOperand;
	int len = str.length();//
	for (int i = 0; i < len; i++)
	{
		ch = str[i];
		switch (ch) {
		case '+':
		case'-':
		case'*':
		case'/':
			DoOperator(ch);
			break;
		default:
			newOperand = (double)(ch-'0');
			addOperand(newOperand);
		}
	}
};

void Calculator::Clear() {
	s.makeEmpty();
}

3.main函数

// Chapter3_表达式.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<iostream>
#include"stack.h"
#include"calculator.h"
#include<string>
#include<math.h>
using namespace std;

bool isDigit(char a)
{
	if (a >= '0'&&a <= '9')return true;

	return false;
}
/*
isp栈内优先数
*/
int isp(char ch)
{
	switch (ch)
	{
	case '#':
		return 0;
	case '(':
		return 1;
	case '*':
	case '/':
	case '%':
		return 5;
	case '+':
	case '-':
		return 3;
	case ')':
		return 6;
	default:
		return -1;
	}
}

/*
icp栈外优先数
*/
int icp(char ch)
{
	switch (ch)
	{
	case '#':
		return 0;
	case '(':
		return 6;
	case '+':
	case '-':
		return 2;
	case '*':
	case '/':
	case '%':
		return 4;
	case ')':
		return 1;
	default:
		return -1;
	}
}

string postfix(string str)
{//把中缀表达式s转换成后缀表达式,设定s中最后一个字符是#
 //并且"#"一开始先放在栈底
	LinkedStack<char> s;
	char ch = '#', ch1, op;
	string tempStr = "";
	int len = str.length();
	s.push(ch);
	int index = 0;
	ch = str[index];

	//a + b*(c + d);
	while (s.IsEmpty() == false)
	{
		if (isDigit(ch))
		{
			tempStr = tempStr + ch;
			index++;
			ch = str[index];
		}
		else {
			s.getTop(ch1);//取栈顶操作符
			if (isp(ch1) < icp(ch)) {
				s.push(ch);
				index++;
				ch = str[index];
			}
			else if (isp(ch1) > icp(ch)) {
				s.pop(op);
				tempStr = tempStr + op;
			}
			else {
				s.pop(op);
				if (op == '(') {
					index++;
					ch = str[index];
				}

			}

		}
	}
	return tempStr;
}
int main()
{
	string temp;
	while (cin >> temp)
	{
		cout << "请输入表达式:" << endl;
		cout << " 并在末尾加个 '#'便于运算:" << endl;		
		cout << "中缀表达式->后缀表达式:"<<postfix(temp)<< endl;

		cout << "后缀表达式比较好处理多项表达式的计算" << endl;
		cout << "现在开始从后缀表达式计算结果" << endl;
		
		Calculator c;
		c.Run(postfix(temp));
		double result; 
		c.s.pop(result);
		cout << result << endl;
		cout << endl;
	}
	
	return 0;
}

总结:

1.写的有点乱,急急忙忙的改完之后就发上来了,有纰漏请指出,不完善/注释不完整也是问题

只要是书上已经注释了,自己看得懂懒得发了,发这里是为了监督自己学习,确实发到了CSDN自己主动性也强了,很开心

2.会不断更新的,自己落下的多.

用两种方式实现表达式自动计算 对栈的应用 (1)中缀表达式转后缀表达式计算(扫两遍) 创建一个数组存储输入的计算表达式。另创建一个数组储存将要生成的后缀表达式。创建一个栈储存操作符。 对已存储的表达式数组扫描。 判断当前节点,如果是操作数或’.’,直接加入后缀表达式中,如果是操作符,则比较前一个操作符与当前操作符的优先级。如果前一个操作符的优先级较高,则将前一个操作符加入后缀表达式中,否则将操作符压入操作符栈。 如果遇到左括号’(’,直接入栈;如果遇到右括号’)’,则在操作符栈中反向搜索,直到遇到匹配的左括号为止,将中间的操作符依次加到后缀表达式中。 当执行完以上操作,发现栈中仍有剩余操作符,则将操作符依次加到后缀表达式中。此时中缀表达式已经转换成了后缀表达式。 对后缀表达式进行计算。 如果后缀表达式为大于0小于9的字符,则将它转换成浮点型数据并存入数栈中。如果遇到操作符,则从数栈中提取两个数,进行相应的运算。依次进行下去,当没有运算符是,运算结束得到最后的结果。 (2)表达式值(扫一遍) 创建一个数组存储输入的计算表达式。创建两个栈,一个字符型的栈,一个双精度型的栈。分别用来存储字符和数。 对已存储的表达式数组扫描。 判断当前节点,如果是操作数和’.’,将字符型的操作数转换为浮点型的数后存入操作数栈。 如果是操作符则判断操作符的优先级。如果字符栈中已存储符号的优先级小于要存入的字符的优先级,则直接让字符入操作符栈。如果字符栈中已存储符号的优先级大于或等于要存入的字符的优先级,则取出操作符栈中的一个字符和操作数栈中的两个数进行计算,然后将结果存入操作数栈中,同上进行下去,直到字符栈中已存储符号的优先级小于要存入的字符的优先级时,将操作符存入操作符栈中。 当遇到左括号’(’,将左括号直接存入操作符栈中。当遇到右括号’)’,则在操作符栈中反向搜索,并且每搜到一个字符就在操作数栈中取两个数进行相应的计算。然后,将运算结果存入到操作符栈中。如此进行下去,直到遇到左括号结束。将左括号从栈中取出。最后,如果操作符栈中还有符号,就从操作符栈顶开始将操作符取出并从操作数栈顶开始取出两个数字进行计算,将结果存入操作数栈中。重复上述操作直到操作符栈中没有操作符,得到运算结果。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值