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

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

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

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

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

1、stack.h

//stack.h
#ifndef STACK_H_
#define STACK_H_

#include
#include
#include
#include

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

const int Max = 10;

//Stack template
template
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 & push(const dataTpye &d);
	Stack & 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
Stack::Stack(int max){
	maxTop = max - 1;
	data = new dataTpye[max];
	top = -1;
}

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

//pop data
template
Stack & Stack::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* symbol;
	Stack* 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(Max);
	digital = new Stack(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
#include
#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!

你可能感兴趣的:(C++,数据结构与算法分析-C++描述)