栈的储存结构及相关操作

栈的储存结构及相关操作

1.实现栈的存储结构及相关操作:进栈、出栈、取栈顶元素等
2.使用该栈完成一个字符串的逆序输出
3.使用该栈完成表达式的括号是否匹配?
4.对算术表达式求值

界面

主要的相关实现函数

template <class T>
class Stack{
	private:
		T* elements;//存放栈中元素的数组
		int top;//栈顶元素的指针
		int maxSize;//栈的最大容纳元素个数
		//void overflowProcess();//栈的溢出处理操作
	public:
		Stack(int size=basesize)//构造函数
		{
			if(size>0){
				maxSize=size;
				top=-1;
				creatStack(size);
			}
		}
		~Stack(){delete []elements;}//析构函数,释放栈的空间
		
		void creatStack(int n);//创建一个大小为n的栈,并为其动态分配空间
		
		void Push(const T& x);//元素x入栈
		
		bool Pop(T& x);//栈顶元素出栈
		
		bool isFull();//判满函数
		
		bool isEmpty();//判空函数
		
		int getMaxsize()//得到栈的最大体积
		{return maxSize;}
		
		T getTopelements();//得到栈顶元素
		
		int getTop()//得到栈的top指针的地址,因为是采用数组类型储存,因此top指针可以利用数组的下标得到
		{return top;}
		
		void print(string tape);//展示各种类型的数据,控制格式
		
		bool writeToFile(string filename);//将数据写入指定文件
		
		bool readFromFile(string filename);//将数据从指定文件读入
};

栈的各个函数的实现

创建一个大小为n的栈

template <class T>
inline void Stack<T>::creatStack(int n)
{
	elements = new T(n);
	
	if(elements==NULL){
		cout<<"动态分配错误!"<<endl;
	}
}

元素x入栈

//如果栈isFull(),则进行溢出处理,否则将其插入到栈顶
template <class T>
inline void Stack<T>::Push(const T &x)
{
	if(isFull()==true){
		//overflowProcess();//溢出处理,调整空间大小
	}
	
	else{
		elements[++top]=x;//将x入栈
	}
}
### 栈顶元素出栈,以x的引用返回

```cpp
//栈顶元素出栈,如果栈为空返回false;若栈不为空,栈顶元素出栈,top指针减一
template <class T>
inline bool Stack<T>::Pop(T& x)
{
	if(isEmpty())return false;
	
	else{
		
		x=getTopelements();
		
		top--;
		return true;
	}
}

判满函数

//判断栈是否满,如果满返回true,未满返回false
template <class T>
inline bool Stack<T>::isFull()
{
	if(this->getTop()<this->getMaxsize()){
		return false;
	}
	else{
		return true;
	}
}

判空函数

//判断栈是否空,如果满返回true,未满返回false
template <class T>
inline bool Stack<T>::isEmpty()
{
	if(this->getTop()==-1){
		return true;
	}
	else{
		return false;
	}
}

打印

template <class T>
inline void Stack<T>::print(string tape)
{
	if(isEmpty()){
		
		cout<<"This Stack is empty!"<<endl;
	}
	
			for(int i=0;i<getTop();i++)
			{
				cout<<"["<<elements[i]<<"]<-";
			}
			
			cout<<"["<<elements[getTop()]<<"]"<<endl;
		
}

得到栈顶元素

template <class T>
inline T Stack<T>::getTopelements()
{
		return elements[getTop()];
}

文件相关读写操作

template <class T>
inline bool Stack<T>::writeToFile(string filename)
{
	ofstream writefile(filename);
	T temp[basesize];
	T x;
	int i,count;
	count=getTop()+1;
	writefile<<count<<endl;
	for(i=0;i<count;i++){
		temp[i]=getTopelements();
		Pop(x);
	}
	for(int j=count-1;j>=0;j--)
	{
		writefile<<temp[j]<<endl;
	}
	return true;
}
template <class T>
inline bool Stack<T>::readFromFile(string filename)
{
	ifstream readfile(filename);
	int len;
	readfile>>len;
	for(int i=0;i<len;i++)
	{
		T temp;
		readfile>>temp;
		this->Push(temp);
	}
	return true;
}

利用栈实现字符串的逆序

void reverseString(char temp[])
{
	int len=strlen(temp);
	Stack<char> st;
	char x;
	char str[len+1];
	//str[len]='';
	for(int i=0;i<len;i++)
	{
		st.Push(temp[i]);
	}
	
	for(int i=0;i<len;i++)
	{
		str[i]=st.getTopelements();
		st.Pop(x);
	}
	str[len]='';
	cout<<"逆序后的字符串为:"<<str<<endl;
}

利用栈实现括号是否匹配的判断

void bracketMatching(char expression[])
{
	Stack<int> stack;
	int j;
	int len=strlen(expression);
	
	for(int i=1;i<=len;i++){
		if(expression[i-1]=='('){
			stack.Push(i);
		}
		
		else if(expression[i-1]==')'){
			if(stack.Pop(j)==true){
				
				cout<<"第"<<j<<"个 “(” 与第"<<i<<"个 “)” 匹配!"<<endl;
				
			}
			else{
				
				cout<<"没有与第"<<i<<"个 “)” 匹配的 “(” !"<<endl;
				
			}
		}
	}
	
	while(stack.isEmpty()==false){
		stack.Pop(j);
		
		cout<<"没有与第"<<j<<"个 “(” 匹配的 “)”!"<<endl;
		
	}

}

利用栈实现表达式的求值

(满足小数,多位数,整数的计算)

其中最重要的算法实现,中缀表达式转后缀表达式,利用容器保存各个操作数,以便实现多位数,小数的实现

//中缀表达式转后缀表达式
vector<string> convert(string input){
	
		Stack<char> stk;//存储操作符栈
		vector<string> temp;
		char s;
		string tmp = "";	
		int length = (int)input.length();//获取表达式的长度
		for(int i = 0; i < length; i++){
			tmp = "";
			
			if((input[i]>='0' && input[i]<='9')){
				tmp += input[i];
				while((i+1<input.size() && input[i+1]>='0' && input[i+1]<='9')||input[i+1] == '.')
				{
						tmp += input[i+1];//若是连续数字
						++i;
				}
				temp.push_back(tmp);
			}
			else if(input[i] == '('){
				//遇到左括号直接入栈
				stk.Push(input[i]);
			}
			else if(input[i] == ')'){
				//如果遇到右括号的话,就把一直到最近的左括号之间的都弹出来加入temp中
				while(stk.getTopelements() != '('){
					tmp += stk.getTopelements();
					temp.push_back(tmp);
					stk.Pop(s);
					tmp="";
				}
				stk.Pop(s);//把左括号弹出栈
			}
			else if(isMark(input[i])){
				//如果是运算符的话,比较他们的优先级再决定是否入栈
				while( prior(input[i])<=prior(stk.getTopelements()) ){
					//如果当前的优先级小于等于栈顶操作符的话,栈顶操作符弹出,加入temp
					tmp += stk.getTopelements();
					temp.push_back(tmp);
					stk.Pop(s);
					tmp="";
				}
				//如果当前的优先级大于栈顶操作符的话,入栈
				stk.Push(input[i]);
			}
		}
		//如果已经扫描到中缀表达式的末尾,就把栈中的操作符都弹出来加入到temp中
		while(!stk.isEmpty()){
			tmp="";
			tmp += stk.getTopelements();
			temp.push_back(tmp);
			stk.Pop(s);
			tmp="";
		}
	return temp;
}

计算表达式的最终结果

//计算后缀表达式的最终数值
double calculate(vector<string> retu){
	
	int i = 0;
	Stack<double> optNum;//定义一个操作数栈
	double s;
	
	double x1,x2 = 0;
	double num;
	
	for(int i = 0;i < retu.size(); i++){//没有遇到结束标志#,即进行表达式的计算
	
	    string tmp = retu[i];
		if(tmp[0] >= '0'&&tmp[0] <= '9'){
			num = atof(tmp.c_str());
			optNum.Push(num);
		}
			else if(retu[i] == "+"){
			x1 = optNum.getTopelements();
			optNum.Pop(s);
			x2 = optNum.getTopelements();
			optNum.Pop(s);
			optNum.Push(x1+x2);
		}
		
		else if(retu[i] == "-"){
			x1 = optNum.getTopelements();
			optNum.Pop(s);
			x2 = optNum.getTopelements();
			optNum.Pop(s);
			optNum.Push(x2-x1);
		}
		
		else if(retu[i] == "*"){
			x1 = optNum.getTopelements();
			optNum.Pop(s);
			x2 = optNum.getTopelements();
			optNum.Pop(s);
			optNum.Push(x1*x2);
		}
		
		else if(retu[i] == "/"){
			x1 = optNum.getTopelements();
			optNum.Pop(s);
			x2 = optNum.getTopelements();
			optNum.Pop(s);
			optNum.Push(x2/x1);
		}
		else if(retu[i] == "%"){
			x1 = optNum.getTopelements();
			optNum.Pop(s);
			x2 = optNum.getTopelements();
			optNum.Pop(s);
			optNum.Push((int)x2%(int)x1);
		}
		else if(retu[i] == "^"){
			x1 = optNum.getTopelements();
			optNum.Pop(s);
			x2 = optNum.getTopelements();
			optNum.Pop(s);
			optNum.Push(pow(x2, x1));
		}
	}
	
	return optNum.getTopelements();//返回最终的计算结果
}
double result(string str){
	str = format(str);
	vector<string> bh = convert(str);
	double k = calculate(bh);
	return k;	
}

对“-”号的特殊化处理

string format(string str){
	for(int i = 0;i < str.length(); i++){
		if(str[i] == '-')
		{
			if(i == 0){
				str.insert(0,1,'0');
			}
			else if(str[i-1] == '('){
				str.insert(i,1,'0');
			}
		}
		
	}
	return str;
}

操作符的优先级

int prior(char op){//求运算符优先级
	switch (op) {
		case '#':
			return -1;
			break;
		case '(':
			return 0;
			break;
		case '+':
			return 1;
			break;
		case '-':
			return 1;
			break;
		case '*':
			return 2;
			break;
		case '/':
			return 2;
			break;
		case '%':
			return 2;
			break;
		case '^':
			return 3;
			break;
		default:
			return -1;
	}
}

完整的代码我已经上传到github,有需要的自行clone,有什么错误的地方欢迎大家指出来,共同学习进步。希望得到大家的支持和鼓励,加油!!!(下一篇更新利用qt,栈的表达式求值,写一个简易的计算器)

Stack栈实现的相关代码

原文地址:https://www.cnblogs.com/xiangjunhong/p/12482473.html