两个队列实现栈

来源:互联网 发布:安卓运行windows 编辑:程序博客网 时间:2024/05/16 09:52
两个队列实现栈:


(一)前提:


//前提已知
typedef struct queue
{
        int queuesize;
        int head, tail;
        int *q;
}Queue;


void InitQueue(Queue *q);
void EnQueue(Queue *q, int key);
int DeQueue(Queue *q);
int SizeOfQueue(Queue *q);
int IsQueueEmpty(Queue *q);
int IsQueueFull(Queue *q);


(二)方法一:


(1)图解:


(2)解析:
q1是专职进出栈的,q2只是个中转站,(q2不存储数据)。
1)入栈时:直接入队列q1即可
2)出栈时:把q1的除最后一个元素外全部转移到队q2中,然后把刚才剩下q1中的那个元素出队列。之后把q2中的全部元素转移回q1中。


(3)代码实现:


void Push(Queue *q1, Queue *q2, int k)
{
        EnQueue(q1, k);
}


int  Pop(Queue *q1, Queue *q2)
{
    int tmp;
    if(IsQueueEmpty(q1) == 1)//队列1为空。
    {
       printf("Stack Empty!\n");
    }
    else
    {
        while(SizeOfQueue(q1) != 1)
        {
            EnQueue(q2, DeQueue(q1));
        }
        tmp = DeQueue(q1);//出栈
        while(IsQueueEmpty(q2) == 0)
        {
            EnQueue(q1, DeQueue(q2));
        }
        return tmp;
    }
}




(4)问题:
出栈时最后仍然需要将q2中的数据压入到q1中。


(三)改进:


(1)解析:
定义两个指针:pushtmp:所指专门进栈的队列; tmp:指向临时作为中转站的另一个栈。
1)入栈时:直接入pushtmp所指队列即可
2)出栈时:把pushtmp的除最后一个元素外全部转移到队列tmp中,然后把刚才剩下q1中的那个元素出队列。然后更新pushtmp,tmp。


比较:方法二,转移到另外一个队列后不用返回了,这样减少了转移的次数。


(2)代码实现:
void Push(Queue *q1, Queue *q2, int k)
{
        Queue *pushtmp, *tmp;
        if(IsQueueEmpty(q1) == 0)//q1非空
        {
            pushtmp = q1;
            tmp = q2;
        }
        else
        {
            pushtmp = q2;
            tmp = q1;
        }
        EnQueue(pushtmp, k);
}


int  Pop(Queue *q1, Queue *q2)
{
    int tmpvalue;
    Queue *pushtmp, *tmp;
    if(!IsQueueEmpty(q1))//q1非空。
    {
        pushtmp = q1;
        tmp = q2;
    }
    else
    {
        pushtmp = q2;
        tmp = q1;
    }


    if(IsQueueEmpty(pushtmp))
    {
       printf("Stack Empty!\n");
    }
    else
    {
        while(SizeOfQueue(pushtmp) != 1)
        {
            EnQueue(tmp, DeQueue(pushtmp));
        }
        tmpvalue = DeQueue(pushtmp);
        return tmpvalue;
    }
}


--------
或者:


思路:


1)若用两个queue实现(可以定义成queue的数组queue q[2]),可以增加一个currentIndex来指向当前选中的queue。
2)入栈操作可以直接把元素加到queue里,即  queue[currentIndex].push(element),时间复杂度为O(1),
3)处理方法是将size()-1个元素从q[currentIndex]转移到空闲队列q[(currentIndex + 1)%2]中,q[currentIndex]最后一个剩下的元素恰对应栈顶元素,之后更新一下currentIndex即可,时间复杂度为O(N)。


4)实现:
#include <iostream>
#include <queue>
#include <cassert>
using namespace std;


template <class T>
class YL_Stack
{
public:
        YL_Stack():currentIndex(0)
        {


        }
        void push(const T &element); //入栈
        void pop();  //出栈
        T top();  //栈顶元素
        size_t size() const;  //栈的大小
        bool empty() const;   //判断栈是否为空




private:
    int currentIndex;
    queue<T> q[2];
};


template <class T>
void YL_Stack<T>::push(const T &element)
{
    q[currentIndex].push(element);
}


template <class T>
size_t YL_Stack<T>::size() const
{
    return q[0].size()+q[1].size();
}


template <class T>
bool YL_Stack<T>::empty() const
{
    return (size()==0);
}


template <class T>
void YL_Stack<T>::pop()
{
    assert(!empty());


    int index=(currentIndex+1)%2;
    while(q[currentIndex].size()>1)
    {
        T temp=q[currentIndex].front();
        q[currentIndex].pop();
        q[index].push(temp);
    }


    q[currentIndex].pop();
    currentIndex=index;    
}


template <class T>
T YL_Stack<T>::top()
{
    assert(!empty());


    int index=(currentIndex+1)%2;
    T temp;
    while(q[currentIndex].size()>0)
    {
        temp=q[currentIndex].front();
        q[currentIndex].pop();
        q[index].push(temp);
    }


    currentIndex=index;
    return temp;
}




void main()
{
    YL_Stack<int> myStack;
    myStack.push(1);
    myStack.push(2);
    myStack.push(3);
    myStack.push(4);
    myStack.push(5);
    cout<<"1栈的大小为:"<<myStack.size()<<endl;
    cout<<"1栈顶元素为:"<<myStack.top()<<endl;
    myStack.pop();
    myStack.pop();
    myStack.pop();
    cout<<"2栈的大小为:"<<myStack.size()<<endl;
    cout<<"2栈顶元素为:"<<myStack.top()<<endl;
        
}
0 0
原创粉丝点击