• 【数据结构笔记】栈


    //栈的类定义 
    const int maxSize=50;
    enum bool{false,true};
    template<class T>
    class Stack
    {
        public:
            Stack(){};
            virtual void Push(const T&x)=0;//新元素x进栈
            virtual bool Pop(T&x)=0; //栈顶元素出栈,由x返回
            virtual bool getTop(T&x)const=0;//读取栈顶元素,由x返回
            virtual bool IsEmpty()const=0;//判断栈空
            virtual bool IsFull()const=0;//判断栈满
            virtual int getSize()const=0;//计算栈中元素的个数 
    } 
    //顺序栈类的定义
    #include<assert.h>
    #include<iostream.h>
    #include"stack.h"
    const int stackIncreament=20;//栈溢出时扩展空间的增量
    template<class T>
    class SeqStack:public Stack<T>
    {
        public:
            SeqStack(int sz=50);//建立一个空栈
            ~SeqStack(){delete[]elements;}//析构函数
            void Push(const T& x)
            bool Pop(T &x);//如果栈是空的则返回flase
            bool getTop(T& x);//如果空则返回false
            bool IsEmpty()const{return (top==-1)?true:false;}
            bool IsFull()const{return (top==maxSize-1)?true:false;}
            int getSize()const (return top+1;)
            void MakeEmpty(){top=-1;}
            friend ostream& operator << (ostream& os,SeqStack<T>& s);
            //输出栈中元素的重载操作
        private:
            T *elements;
            int top;
            int maxSize;
            void overflowProcess();//栈溢出的处理 
    };
    
    //顺序栈的构造函数
    template<class T>
    SeqStack<T>::SeqStack(int sz):top(-1),maxSize(sz)
    {
        elements=new T[maxSize];
        assert(elements!=NULL);//断言机制,若为真程序则继续运行下面的 
    } 
    
    //扩充栈的存储空间
    template<class T>
    void SeqStack<T>::overflowProcess()
    {
        T *newarray=new T[maxSize+stackIncreament];
        if(newArray==NULL)
        {
            cerr<<"存储分配失败!"<<endl;
            exit(1);
        }
        for(int i=0;i<=top;i++) newArray[i]=element[i];
        maxSize=maxSize+stackIncreament;
        delete []elements;
        elements=newArray;
    }
    
    template<class T>
    void SeqStack<T>::Push(const T& x)
    {
        if(IsFull()==true) overflowProcess();
        elements[++top]=x;
    }
    
    template<class T>
    bool SeqStack<T>::Pop(T& x)
    {
        if(IsEmpty()==true) return false;
        x=elements[top--];
        return true;
    }
    
    template<class T>
    bool Seqstack<T>::getTop(T& x)
    {
        if(IsEmpty()==true) return false;
        x=elements[top];
        return true;
    } 
    
    //输出栈中元素的重载操作 
    template<class T>
    ostream& operator << (ostream& os,SeqStack<T>& s)
    {
        os<<"top="<<s.top<<endl;
        for(int i=0;i<=s.top;i++)
        {
            os<<i<<":"<<s.elements[i]<<endl;
        }
        return os;
    };
    
    //栈的空间共享 双栈的插入和删除
    bool push(DualStack& DS,T x,int d)     
    //在双栈中扎入元素x,d=0插在第0号栈,d!=0插在第1号栈 
    {
        if(DS.t[0]+1==DS.t[1]) return false;//栈满了 
        if(d==0) DS.t[0]++;
        else DS.t[1]--;
        DS.Vector[DS.t[d]]=x;
        return true;
    };
    
    bool Pop(DualStack& DS,T& x,int d)
    //从双栈中推出栈顶元素,通过x返回。d=0从第0号栈推栈,d!=0从第1号栈退栈 
    {
        if(DS.t[d]==DS.b[d]) return false;
        x=DS.Vector[DS.t[d]];
        if(d==0) DS.t[0]--;
        else DS.t[1]++;
        return true;
    };
    
    //链式栈
    #include<iostream.h>
    #include"LinkedList.h"
    #include"stack.h"
    template<class T>
    class LinkedStack:public Stack<T>   //链式栈类定义 
    {
        public:
            LinkedStack():top(NULL){}   //构造函数,置空栈 
            ~LinkedStack(){makeEmpty();} //析构函数 
            void Push(const T&x);
            bool Pop(T&x);
            bool getTop(T& x);
            bool IsEmpty()const{return (top==NULL)?true:false;}
            int getSize()const;
            void makeEmpty();         
            friend ostream&operator << (ostream& os,SeqStack<T>& s);
            //输出栈中元素的重载操作<<
        private:
            LinkNode<T>*top;           //栈顶指针,即链头指针 
    };
     
     
    template<class T>
    LinkedStack<T>makeEmpty()
    {
        //逐次删去链式栈中的元素直至栈顶指针为空
        LinkNode<T>*p;
        while(top!=NULL)
        {
            p=top;top=top->link;delete p;
        } 
    };
     
    template<class T>
    void LinkedStack<T>::Push(const T& x)
    {
        top=new LinkNode<T>(x,top);//创建新节点的link为top
        assert(top!=NULL); 
    };
    
    template<class T>
    bool LinkedStack<T>::Pop(T& x)
    {
        if(IsEmpty()) return false;
        LinkNode<T>*p=top;
        top=top->link;
        x=p->data;delete p;
        return true;
    };
    
    template<class T>
    int LinkStack<T>::getTop(T& x)const
    {
        if(IsEmpty()) return false;
        x=top->data;
        return true;
    }
    
    template<class T>
    int LinkedStack<T>::getSize()const
    {
        LinkNode<T>*p=top;int k=0;
        while(top!=NULL)
        {
            top=top->link;
            k++;
        }
        return k;
    };
    
    //输出栈中元素的重载操作 
    template<class T>
    ostream& operator << (ostream& os,LinkedStack<T>& s)
    {
        os<<"栈中元素的个数="<<s.getSize()<<endl;
        LinkNode<T>*p=S.top();int i=0;
        while(p!=NULL)
        {
            os<<++i<<":"<<p->data<<endl;
            p=p->link; 
        } 
        return os;
    };
    
    /*
    如果同时使用n个链式栈,其头指针数组可以用一下方式定义:
    LinkNode<T>*s=new LinkNode<T>[n]; 
    */ 
    //栈的应用---括号匹配 
    #include<iostream.h>
    #include<string.h>
    #include<stdio.h>
    #include"stack.h"
    const int maxLength=100;
    void PrintMatchedPairs(char *expression)
    {
        Stack<int>s(maxLength);
        int j,length=strlen(expression);
        for(int i=1;i<length;i++)
        {
            if(expression[i-1]=='(') s.Push(i);
            else if(expression[i-1]==')')
            {
                if(s.Pop(j))cout<<j<<""<<i<<"匹配"<<endl;
                else cout<<"没有与第"<<i<<"个右括号匹配的左括号!"<<endl; 
            }
        }
        while(s.IsEmpty()==false)
        {
            s.Pop(j);
            cout<<"没有与第"<<j<<"个左括号相匹配的右括号!"<<endl; 
        }
    }
    
    //栈的应用--表达式计算
    #include<math.h>
    #include<stack.h>
    #include<iostream.h>
    class Calculator
    {
        //模拟一个简单的计算器。此计算机对后缀表达式求值。 
        public:
           Calculator(int sz):s(sz){}
           void Run();
           void Clear();
         private:
             Stack<double>s;
             void AddOperand(double value);    //进操作数栈
            bool get2Operands(double& left,double& right);//从栈中退出两个操作数
            void DoOperator(char op);          //形成运算指令,进行计算 
    };
    
    
    void Calculator::DoOperator(char op)
    {
        //私有函数:取俩个操作数,根据操作符op形成运算指令并计算
        double left,right,vlaue;int result;
        result=Get2Operands(left,right);
        if(result==true) 
        {
            switch(op)
            {
                case'+':value=left+right;s.Push(value);break;
                case'-':value=left-right;s.Push(value);break;
                case'*':value=left*right;s.Push(value);break;
                case'/':if(right==0.0)
                {
                    cerr<<"Divide by 0!"<<endl;
                    Clear();
                }else{value=left/right;s.Push(value);}
                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)
    {
        s.Push(value); 
    };
    
    void Calculator::Run()
    {
        //读取一个字符串并求一个后缀表达式的值。以字符'#'结束。
        char ch;double newOperand;
        while(cin>>ch,ch!='#')
        {
            switch(ch)
            {
                case'+':case'-':case'*':case'/':DoOpertor(ch);break;
                default:cin.putback(ch);//将字符放回输入流 
                cin>>newOperand;
                AddOperand(newOperand); //将操作数放入栈中 
            }
        } 
    };
    
    void Calculator::Clear()
    {
        S.makeEmpty();
    };
    
    //将中缀表达式转换为后缀表达式的算法
    
    
    void postfix(expression e)
    {
        /*
        把中缀表示e转换成后缀表示并输出,设定e中最后一个符号是'#',而且'#'一开始就放在
        栈s的栈底。 
        */
        Stack<char>s;//定义栈的对象s,其元素为字符。 
        char ch='#',ch1,op;
        s.Push(ch);cin.get(ch);
        while(s.IsEmpty()==false&&ch!='#')
        {
            if(isdigit(ch)) {cout<<ch;cin.get(ch);}//是操作数,输出
            else
            {
                s.getTop(ch1);//从栈顶取出操作符ch1;
                if(isp(ch1)<icp(ch)) //新输入操作符ch优先级高 
                {
                    s.Push(ch);cin.Get(ch);//进栈,读取下一个字符 
                }else if(isp(ch1)>icp(ch)) //新输入操作符优先级低 
                {
                    s.Pop(op);cout<<op; //退栈并输出 
                } else 
                {
                    s.Pop(op);           //输入操作符优先级等于栈顶优先级 
                    if(op=='(') cin.Get(ch); 
                }
            } 
        } 
    } 
  • 相关阅读:
    WDNMD组——项目需求分析
    2020软件工程作业——团队03
    2020软件工程作业——团队02
    WDNMD——团队展示
    spring boot:redis+lua实现顺序自增的唯一id发号器(spring boot 2.3.1)
    linux(centos8):安装kubernetes worker节点并加入到kubernetes集群(kubernetes 1.18.3)
    linux(centos8):kubernetes安装的准备工作
    kubernetes:用label让pod在指定的node上运行(kubernetes1.18.3)
    kubernetes:用kubeadm管理token(kubernetes 1.18.3)
    linux(centos8):kubeadm单机安装kubernetes(kubernetes 1.18.3)
  • 原文地址:https://www.cnblogs.com/zzyh/p/12828228.html
Copyright © 2020-2023  润新知