数据结构与算法分析-C++描述 第3章 栈ADT(简单计算器设计)

博客介绍了栈的定义,它是限制插入和删除在栈顶的表。阐述了栈的两种实现方式,即链表和数组实现。还列举了栈的常见应用,如平衡符号、后缀表达式运算等。最后给出使用堆栈完成简单整数带括号四则混合运算的实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       栈(stack)是限制插入和删除只能在同一位置上进行的表(又称LIFO表),该位置是表的末端,称为栈顶。

      栈的两种实现:1)栈的链表(单向链表)实现; 2)栈的数组(vector)实现;

       栈的常见应用:1)平衡符号,用于编译器语法检错;2)后缀表达式:通过栈的形式完成数学运算,时间复杂度为O(N),执行效率高;3)中缀到后缀的转换;4)函数调用:堆和栈相互配合递归调用存储器存储的函数地址和对应的值。

       实例:使用堆栈完成简单整数带括号的四则混合运算

1、stack.h

//stack.h
#ifndef STACK_H_
#define STACK_H_

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>

using std::cout;
using std::endl;
using std::string;

const int Max = 10;

//Stack template
template<class dataTpye>
class Stack{
private:
	int top;
	int maxTop;
	dataTpye* data;
public:
	Stack(int max = 10);
	~Stack(){delete[] data;};
	bool isEmpty(){return top == -1;};
	bool isFull(){return top == maxTop;};
	Stack<dataTpye> & push(const dataTpye &d);
	Stack<dataTpye> & pop(dataTpye &d);
	dataTpye getTop() const{return data[top];};
	void clear(){top = -1;};
	void print(){
		for(int i = 0; i < top + 1; i++){
			cout << data[i] << " ";
		}
		cout << endl;
	}
};

//Stack constructor
template<class dataTpye>
Stack<dataTpye>::Stack(int max){
	maxTop = max - 1;
	data = new dataTpye[max];
	top = -1;
}

//push data
template<class dataTpye>
Stack<dataTpye> & Stack<dataTpye>::push(const dataTpye &d){
	if(isFull()){
		cout << "the Stack is already full !" << endl;
		return *this;
	}
	else{
		data[++top] = d;
		return *this;
	}
}

//pop data
template<class dataTpye>
Stack<dataTpye> & Stack<dataTpye>::pop(dataTpye &d){
	if(isEmpty()){
		cout << "the Stack is already empty !" << endl;
		return *this;
	}
	else{
		d = data[top--];
		return *this;
	}
}

//judge where the character is a number nr not
bool isNum(char ch){
	if(ch >= '0' && ch <= '9'){
		return true;
	}
	else{
		return false;
	}
}

//omit the blank in string expression
void omitBlank(string &s){
	string::iterator i = s.begin();
	while((i = find(i, s.end(), ' ')) != s.end()){
		s.erase(i);
	}
}

//Calculator class
class Calculator{
private:
	string s;
	Stack<char>* symbol;
	Stack<int>* digital;
public:
	Calculator(string s);
	~Calculator();
	void init(string const s);
	int outerPriority(char outer);
	int innerPriority(char inner);
	bool judge(char outer, char inner);
	int judge(char op);
	void assign();
	int calculate();
};

//Calculator constructor
Calculator::Calculator(string s){
	init(s);
	symbol = new Stack<char>(Max);
	digital = new Stack<int>(Max);
}

//Calculator destructor
Calculator::~Calculator(){
	delete symbol;
	delete digital;
}

//Calculator init string
void Calculator::init(string const s){
	this -> s = "#" + s + "#";
	omitBlank(this -> s);
}

//outer priority outside ()
int Calculator::outerPriority(char outer){
	switch(outer){
		case '#' : return 0;
		case '(' : return 8;
		case '+' : return 2;
		case '-' : return 2;
		case '*' : return 4;
		case '/' : return 4;
		case '%' : return 4;
		case '^' : return 6;
		case ')' : return 1;
		default:
				throw 1;
	}
}

//inner priority inside ()
int Calculator::innerPriority(char inner){
	switch(inner){
		case '#' : return 0;
		case '(' : return 1;
		case '+' : return 3;
		case '-' : return 3;
		case '*' : return 5;
		case '/' : return 5;
		case '%' : return 5;
		case '^' : return 7;
		case ')' : return 8;
		default : throw 1;
		 
	}
}

//judge the priority between outer and inner
bool Calculator::judge(char outer, char inner){
	return outerPriority(outer) > innerPriority(inner);
}

//judge the operator
int Calculator::judge(char op){
	switch(op){
		case '#' : return -1;
		case ')' : return 0;
		default : return 1;
	}
}

//assign the operation based on symbol stack
void Calculator::assign(){
	char temp = 0;
	int data1 = 0;
	int data2 = 0;
	symbol -> pop(temp);
	digital -> pop(data1);
	digital -> pop(data2);
	switch(temp){
		case '+' : 
			data2 += data1;
			break;
		case '-' :
			data2 -= data1;
			break;
		case '*' :
			data2 *= data1;
			break;
		case '/' :
			if(data1 == 0){
				cout << "denominator can't be 0 !" << endl;
				throw 0;
			}
			else{
				data2 /= data1;
				break;
			}
		case '%' :
			data2 %= data1;
			break;
		case '^' :
			data2 = pow(data2, data1);
			break;
		default:
			throw 1;
	}
	digital -> push(data2);
}

//calculate the result based on the string characters
int Calculator::calculate(){
	for(int i = 0; i < s.size(); i++){
		if(isNum(s[i])){
			int num = s[i] - '0';
			int temp = 0;
			if(num > 0 && isNum(s[i-1])){
				digital -> pop(temp);
				num += temp * 10;
			}
			digital -> push(num);
		}
		else{
			char temp = s[i];
			if(symbol -> isEmpty()){
				symbol -> push(temp);
			}
			else{
				//judge priority between temp and symbol top
				if(judge(temp, symbol -> getTop())){
					symbol -> push(temp);
				}
				// case # symbol
				else if(judge(temp) == -1){
					while(symbol -> getTop() != '#'){
						assign();
					}
					int result = digital -> getTop();
					symbol -> clear();
					digital -> clear();
					return result;
				}
				//case ( symbol
				else if(judge(temp) == 0){
					while(symbol -> getTop() != '('){
						assign();
					}
					symbol -> pop(temp);
				}
				// case otherwise
				else if(judge(temp) == 1){
					while(! judge(temp, symbol -> getTop())){
						assign();
					}
					symbol -> push(temp);
				}
			}
		}
	}
}

#endif

2、 main.cpp

//main.cpp
#include<iostream>
#include<cstring>
#include"stack.h"

using namespace std;

int main()
{
	try{
		string s = "";
		Calculator calculator(s);
		bool flag = true;
		char ch;
		while(flag){
			cout << "enter an expression : ";
			getline(cin, s);
			calculator.init(s);
			cout << " the calculate result is : " << calculator.calculate() << endl;
			cout << "enter Y or N to continue or not : ";
			cin >> ch;
			if(ch == 'Y' || ch == 'y'){
				flag = true;
				cin.get();
			}
			else if(ch == 'N' || ch == 'n'){
				flag = false;
				cin.get();
			}
			else{
				cout << "only Y or N avaible, I will exit !" << endl;
				flag = false;
			}
		}
		cout << " done." << endl;
	
	}
	catch(int i){
		if(i == 0){
			cout << "denominator can't be 0! " << endl; 
		}
		else if(i == 1){
			cout << "wrong expression, please check it again !" << endl;
		}
	}
	return 0;
}

practice makes perfect!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值