算法导论 使用两个栈实现队列

使用两个栈实现队列

1. 如何使用两个栈实现队列?

因为栈的顺序是后进先出,队列是先进先出。通过把一个栈“倒”进第二个栈,可以在第二个栈以原来入栈的顺序出栈,就达到了队列的先进先出效果。
注意关于如何“倒”,也有效率的高低之分。
我使用的方法是(一个栈称StackIn,另一个栈称StackOut):
1.当入队列时,不用判断StackOut有没有元素,只要没达到队列的上限,就直接压入StackIn。
2.当出队列时,如果StackOut不为空,直接弹出StackOut的栈顶元素;如果StackOut是空的,那么让StackIn的元素先倒进StackOut,再从StackOut弹出栈顶元素。
这种方法时间复杂度是相对其他几种方法比较低的。关于另外几种如何“倒”的方法,更详细的介绍,可以看另一篇博文:http://www.cnblogs.com/wanghui9072229/archive/2011/11/22/2259391.html

2. 使用两个栈实现队列的实现(C++代码)

//SequeStack.h
#pragma once

#include <assert.h>

template<typename ElemType>
class SequeStack
{
public:
    SequeStack(unsigned int size);
    bool Push(ElemType elem);
    bool Pop(ElemType* retElem);
    bool Empty() const;
    bool Visit(ElemType* elem, unsigned int pos) const;
    bool Full() const;
    unsigned int const& GetLength() const;
private:
    ElemType* m_array;
    unsigned int m_top;
    unsigned int m_size;
    unsigned int m_length;
};

template<typename ElemType>
unsigned int const& SequeStack<ElemType>::GetLength() const
{
    return m_top;
}

template<typename ElemType>
bool SequeStack<ElemType>::Full() const
{
    return m_top >= m_size ? true : false;
}

template<typename ElemType>
bool SequeStack<ElemType>::Visit(ElemType* elem, unsigned int pos) const
{
    if (pos >= m_size || pos < 0)
    {
        assert(false && "Error: Visit Pos is out range of array!");
        return false;
    }
    *elem = m_array[pos];
    return true;
}


template<typename ElemType>
bool SequeStack<ElemType>::Empty() const
{
    return m_top ? false : true;
}

template<typename ElemType>
bool SequeStack<ElemType>::Pop(ElemType* retElem)
{
    if (Empty())
    {
        assert(false && "Error: SequeStack is underflow!");
        return false;
    }
    else
    {
        *retElem = m_array[--m_top];
        return true;
    }
}

template<typename ElemType>
bool SequeStack<ElemType>::Push(ElemType pushElem)
{
    if (m_top == m_size)
    {
        assert(false && "Error: SequeStack is overflow!");
        return false;
    }
    else
    {
        m_array[m_top++] = pushElem;
        return true;
    }

}

template<typename ElemType>
SequeStack<ElemType>::SequeStack(unsigned int size)
    : m_array(new ElemType[size]),m_top(0),m_size(size),m_length(0)
{
    memset(m_array,0,sizeof(ElemType)*size);
}
//QueueByTwoStack.h
#pragma once

#include <assert.h>
#include "SequeStack.h"

template<typename ElemType>
class QueueByTwoStack
{
public:
    QueueByTwoStack(unsigned int size);
    bool DeQueue(ElemType* elem);
    bool EnQueue(const ElemType& elem);
    bool Empty() const;
    bool Visit(ElemType* elem, const unsigned int& pos) const;
    unsigned int GetLength() const;
private:
    bool StackInToStackOut();
    SequeStack<ElemType>* m_stackIn;
    SequeStack<ElemType>* m_stackOut;
    unsigned int m_size;
};

template<typename ElemType>
unsigned int QueueByTwoStack<ElemType>::GetLength() const
{
    return m_stackIn->GetLength() + m_stackOut->GetLength();
}

template<typename ElemType>
bool QueueByTwoStack<ElemType>::StackInToStackOut()
{
    if (!m_stackOut->Empty()) // StackOut必须为空才能倒
    {
        return false;
    }

    while(!m_stackIn->Empty()) //现在将m_stackIn倒进m_stackOut
    {
        ElemType tempElem;
        m_stackIn->Pop(&tempElem);
        m_stackOut->Push(tempElem);
    }
    return true;
}

template<typename ElemType>
bool QueueByTwoStack<ElemType>::Visit(ElemType* elem, const unsigned int& pos) const
{
    if (pos >= m_size)
    {
        return m_stackOut->Visit(elem, pos - m_size);
    }
    else
    {
        return m_stackIn->Visit(elem, pos);
    }
}

template<typename ElemType>
bool QueueByTwoStack<ElemType>::Empty() const
{
    if (m_stackIn->Empty() && m_stackOut->Empty())
        return true;
    return false;
}

template<typename ElemType>
bool QueueByTwoStack<ElemType>::EnQueue(const ElemType& elem)
{
    if ( m_stackIn->Push(elem) && GetLength() <= m_size )
    {
        return true;
    }
    assert(false && "Error: SequeDeQueue is overflow!");
    return false;
}

template<typename ElemType>
bool QueueByTwoStack<ElemType>::DeQueue(ElemType* elem)
{
    if (Empty())
    {
        assert(false && "Error: SequeDeQueue is underflow!");
        return false;
    }

    StackInToStackOut(); //尝试倒进stackOut

    return m_stackOut->Pop(elem);
}

template<typename ElemType>
QueueByTwoStack<ElemType>::QueueByTwoStack(unsigned int size)
    :m_stackIn(new SequeStack<ElemType>(size)),m_stackOut(new SequeStack<ElemType>(size)),m_size(size)
{

}
//Util.h
#pragma once

namespace Util
{
    template<typename T>
    void PrintMemory(const T& dateStruct, unsigned int size)
    {
        cout << "PrintMemory: ";
        for (int i = 0; i != size; i++)
        {
            ElemType tempElem;
            dateStruct.Visit(&tempElem,i);
            printf("%d ",tempElem);
        }
        printf("\n");
        printf("\n");
    }
}
#include "Util.h"
#include "QueueByTwoStack.h"
#include <iostream>

using namespace std;

typedef int ElemType;

int main()
{

    const int QUEUE_SIZE = 6;
    QueueByTwoStack<int> testQueueByTwoStack(QUEUE_SIZE);

    cout << "testQueueByTwoStack is " << (testQueueByTwoStack.Empty() ? "Empty." : "Not Empty.") << endl;
    Util::PrintMemory(testQueueByTwoStack,QUEUE_SIZE*2);

    for (int i = 0; i != 4; i++) //4个元素入队列{1、2、3、4}
    {
        testQueueByTwoStack.EnQueue(i+1);
        cout << "EnQueue:" << i+1 << endl;
        cout << "testQueueByTwoStack is " << (testQueueByTwoStack.Empty() ? "Empty." : "Not Empty.") << endl;
        Util::PrintMemory(testQueueByTwoStack,QUEUE_SIZE*2);
    }

    for (int i = 0; i != 2; i++) //2个元素出队列{1、2}
    {
        ElemType tempElem;
        testQueueByTwoStack.DeQueue(&tempElem);
        cout << "DeQueue:" << tempElem << endl;
        cout << "testQueueByTwoStack is " << (testQueueByTwoStack.Empty() ? "Empty." : "Not Empty.") << endl;
        Util::PrintMemory(testQueueByTwoStack,QUEUE_SIZE*2);
    }

    for (int i = 0; i != 4; i++) //4个元素入队列{5、6、7、8}
    {
        testQueueByTwoStack.EnQueue(i+5);
        cout << "EnQueue:" << i+5 << endl;
        cout << "testQueueByTwoStack is " << (testQueueByTwoStack.Empty() ? "Empty." : "Not Empty.") << endl;
        Util::PrintMemory(testQueueByTwoStack,QUEUE_SIZE*2);
    }

    for (int i = 0; i != 6; i++) //6个元素出队列{3、4、5、6、7、8}
    {
        ElemType tempElem;
        testQueueByTwoStack.DeQueue(&tempElem);
        cout << "DeQueue:" << tempElem << endl;
        cout << "testQueueByTwoStack is " << (testQueueByTwoStack.Empty() ? "Empty." : "Not Empty.") << endl;
        Util::PrintMemory(testQueueByTwoStack,QUEUE_SIZE*2);
    }

    return 0;
}

3. 程序运行结果

testQueueByTwoStack is Empty.
PrintMemory: 0 0 0 0 0 0 0 0 0 0 0 0

EnQueue:1
testQueueByTwoStack is Not Empty.
PrintMemory: 1 0 0 0 0 0 0 0 0 0 0 0

EnQueue:2
testQueueByTwoStack is Not Empty.
PrintMemory: 1 2 0 0 0 0 0 0 0 0 0 0

EnQueue:3
testQueueByTwoStack is Not Empty.
PrintMemory: 1 2 3 0 0 0 0 0 0 0 0 0

EnQueue:4
testQueueByTwoStack is Not Empty.
PrintMemory: 1 2 3 4 0 0 0 0 0 0 0 0

DeQueue:1
testQueueByTwoStack is Not Empty.
PrintMemory: 1 2 3 4 0 0 4 3 2 1 0 0

DeQueue:2
testQueueByTwoStack is Not Empty.
PrintMemory: 1 2 3 4 0 0 4 3 2 1 0 0

EnQueue:5
testQueueByTwoStack is Not Empty.
PrintMemory: 5 2 3 4 0 0 4 3 2 1 0 0

EnQueue:6
testQueueByTwoStack is Not Empty.
PrintMemory: 5 6 3 4 0 0 4 3 2 1 0 0

EnQueue:7
testQueueByTwoStack is Not Empty.
PrintMemory: 5 6 7 4 0 0 4 3 2 1 0 0

EnQueue:8
testQueueByTwoStack is Not Empty.
PrintMemory: 5 6 7 8 0 0 4 3 2 1 0 0

DeQueue:3
testQueueByTwoStack is Not Empty.
PrintMemory: 5 6 7 8 0 0 4 3 2 1 0 0

DeQueue:4
testQueueByTwoStack is Not Empty.
PrintMemory: 5 6 7 8 0 0 4 3 2 1 0 0

DeQueue:5
testQueueByTwoStack is Not Empty.
PrintMemory: 5 6 7 8 0 0 8 7 6 5 0 0

DeQueue:6
testQueueByTwoStack is Not Empty.
PrintMemory: 5 6 7 8 0 0 8 7 6 5 0 0

DeQueue:7
testQueueByTwoStack is Not Empty.
PrintMemory: 5 6 7 8 0 0 8 7 6 5 0 0

DeQueue:8
testQueueByTwoStack is Empty.
PrintMemory: 5 6 7 8 0 0 8 7 6 5 0 0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值