zoukankan      html  css  js  c++  java
  • 栈的储存结构及相关操作

    栈的储存结构及相关操作

    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栈实现的相关代码

  • 相关阅读:
    leaflet之自定义marker Icon
    Geoserver系列教程
    leaflet教程
    浏览器缓存详解:expires,cache-control,last-modified,etag详细说明
    给自己,这周一个任务,完成一个组件化的图片轮播效果
    撩课-Java每天10道面试题第4天
    撩课-Java每天10道面试题第3天
    撩课-Java每天10道面试题第2天
    撩课-Java每天10道面试题第1天
    撩课-Mysql详解第3部分sql分类
  • 原文地址:https://www.cnblogs.com/xiangjunhong/p/12482473.html
Copyright © 2011-2022 走看看