zoukankan      html  css  js  c++  java
  • 两个栈实现队列 以及两个队列实现栈

    1.用两个栈来实现队列,栈是先进后出的,队列是先进先出的,这时,我们可以用stack1来专门入栈,stack2来专门出栈,具体地:

    入队:直接入栈到stack1

    出队:检测stack2是否为空,如果为空,则将stack1的所有元素移动到stack2中,

                 再次判断stack2是否为空,如果为空抛出异常;

                 如果非空,将stack2的栈顶元素出队。

    代码如下:

    #include <iostream>
    #include <stack>
    using namespace std;
    //用两个栈实现一个队列stack1专门用来入队  stack2专门用来出队
    template<class T>class Queue
    {
    public:
        Queue(void){};
        ~Queue(void){};
        void AppendTail(const T &ele);
        T DeleHead();
    private:
        stack<T>stack1;
        stack<T>stack2;
    
    };
    
    //stack1专门用来入栈
    template<class T> void Queue<T>::AppendTail(const T &ele)
    {
        stack1.push(ele);
    }
    //stack2作为临时缓冲,将stack1入栈的元素逆序 然后出栈即可实现先入先出
    template<class T> T Queue<T>::DeleHead()
    {
        if (stack2.size()<=0)//stack2空 则将stack1的元素都放在stack2中
        {
            while (stack1.size()>0)
            {
                T node=stack1.top();
                stack2.push(node);
                stack1.pop();
            }
        }
        if (stack2.size()==0)//判断栈是否为空
        {
            cout<<"empty"<<endl;
            throw new exception();
        }
        T RetNode =stack2.top();//返回stack2的栈顶元素
        stack2.pop();//出栈
        return RetNode;
    }
    
    void main()
    {
        Queue<int>*pQu=new Queue<int>();
        pQu->AppendTail(1);
        pQu->AppendTail(2);
        pQu->AppendTail(3);
    
        cout<<pQu->DeleHead()<<endl;
        pQu->AppendTail(4);
        pQu->AppendTail(5);
        cout<<pQu->DeleHead()<<endl;
        cout<<pQu->DeleHead()<<endl;
        cout<<pQu->DeleHead()<<endl;
        cout<<pQu->DeleHead()<<endl;
        cout<<pQu->DeleHead()<<endl;
    
    }

      

    队列是先进先出的,而栈是后进先出的,那么我们如何用两个队列实现栈的操作呢?

    方法一:

          我们可以让queue1专门用来入栈和出栈操作,让queue2作为储存queue1的n-1个元素,也就是除了最后一个入队元素,然后将queue1中的最后元素出列,然后将queue2中的  n-1个元素放回queue1.

      思路

      q1是专职进出栈的,q2只是个中转站

      入栈时:直接入队列q1即可

      出栈时:把q1的除最后一个元素外全部转移到队q2中,然后把刚才剩下q1中的那个元素出队列。之后把q2中的全部元素转移回q1中。

      如下图所:

      

    #include <queue>
    #include <iostream>
    using namespace std;
    template <class T>
    class Stack
    {
    public:
    	Stack(){};
    	~Stack(){};
    	void StackPush(const T&data);
    	T StackPop();
    private:
    	queue<T>que1;
    	queue<T>que2;
    };
    //que1专门用来入栈
    template<class T> void Stack<T>::StackPush(const T&data)
    {
    	que1.push(data);
    }
    //que2作为临时存储que1的多余变量,当出栈后要将所有元素还给que1
    template<class T> T Stack<T>::StackPop()
    {
    	if (que1.size()<=0)
    	{
    		cout<<"empty"<<endl;
    		throw new exception("empty");
    	}
    	else//que1的变量大于等于1个时
    	{
    		while(que1.size()>1)//将最先入n-1个元素的存que2中
    		{
    			que2.push(que1.front());
    			que1.pop();
    		}
    		T RetData=que1.front();//返回最后入的元素
    		que1.pop();
    		while(que2.size()>0)//再将que2的元素存回que1
    		{
    			que1.push(que2.front());
    			que2.pop();
    		}
    		return RetData;
    	}
    }
    
    void main()
    {
    	Stack<int > *pSt=new Stack<int >();
    	pSt->StackPush(1);
    	pSt->StackPush(2);
    	pSt->StackPush(3);
    	cout<<pSt->StackPop()<<endl;
    	cout<<pSt->StackPop()<<endl;
    	cout<<pSt->StackPop()<<endl;
    //	cout<<pSt->StackPop()<<endl;//抛异常
    }
    

      结果如下图:

      然后我们发现,如果队列中元素较多时,每当移除一个元素,那么剩余的n-1个元素都要拷贝进queue2,然后再从queue2拷进queue1,这样增加了时间复杂度,那么能不能有其他更好的办法呢?

    方法二:

      让两个栈都当做出栈或者入栈的队列,当入栈时候,先选定一个que1入栈,当出栈时候将que1的n-1个元素移动que2。那么下一次出栈的队列为que2,再将n-1个元素移动到que1,依次.....

      那么入栈时候该选择哪个呢?很显然,入栈也是来回变的,每当有一次出栈操作时,下次入栈时所选的队列都会改变,这时候我们只需要一个标志位flag来选定该入哪个队列就好了。

      代码如下:

    #include <queue>
    #include <iostream>
    using namespace std;
    template <class T>
    class Stack
    {
    public:
        Stack(){};
        ~Stack(){};
        void StackPush(const T&data);
        T StackPop();
    private:
        queue<T>que1;
        queue<T>que2;
        static bool flag;//用来标识该在哪个队列入栈的标识 
    };
    
    
    template<class T> bool Stack<T>::flag=true;//初始化为TRUE 在que1中入栈
    template<class T> void Stack<T>::StackPush(const T&data)
    {
        queue<T>*quTemp=NULL;//用于指向要入栈的队列,注意初始化格式
        if (flag)//标识用来决定该入栈到哪个队列
        {
            quTemp=&que1;
        }
        else 
        {
            quTemp=&que2;
        }
        quTemp->push(data);
    }
    
    
    template<class T> T Stack<T>::StackPop()
    {
        flag=!flag;//将标识取反
        queue<T>*popTemp=NULL;//用于出栈的临时队列
        queue<T>*saveTemp=NULL;//用于保存n-1个多余变量的队列
        if (que1.size()>=1)
        {
            popTemp=&que1;
            saveTemp=&que2;
        }
        else
        {
            popTemp=&que2;
            saveTemp=&que1;
        }
        if (popTemp->size()<=0)
        {
            cout<<"Empty"<<endl;
            throw new exception("the stack is empty");
        }
        while(popTemp->size()>1)//出栈的队列中元素大于1个 移动到另一个队列中
        {
            saveTemp->push(popTemp->front());
            popTemp->pop();
        }
        T RetVal=popTemp->front();//返回最后一个元素
        popTemp->pop();
        return RetVal;
    }
    
    
    void main()
    {
        Stack<int> *pSt=new Stack<int>();
        
        pSt->StackPush(1);
        pSt->StackPush(2);
        pSt->StackPush(3);
         cout<<pSt->StackPop()<<endl;
        cout<<pSt->StackPop()<<endl;
    
        pSt->StackPush(4);
        pSt->StackPush(5);    
    
        cout<<pSt->StackPop()<<endl;
        cout<<pSt->StackPop()<<endl;
        cout<<pSt->StackPop()<<endl;
    
    }

    运行结果如下图所示:

     

  • 相关阅读:
    leetcode Power of Two
    leetcode Merge Two Sorted Lists
    Mac linux 安装memcached服务 用法
    Vsftp配置都没有问题 连接不上 530 Login incorrect 解决方法
    mysql 远程连接不上 %用户已经添加了
    Centos yum 安装mysql报错 No package mysql-server available.
    Linux 查询程序安装路径 是否安装
    php报错 Call to undefined function mb_stripos()
    mac编译openssl扩展报错 openssl.c:44:10: fatal error: 'openssl/evp.h' file not found
    在安装mysqli的时候,出现error: ext/mysqlnd/mysql_float_to_double.h: No such file or direc
  • 原文地址:https://www.cnblogs.com/mu-tou-man/p/3954032.html
Copyright © 2011-2022 走看看