1. 程式人生 > >用單鏈表實現棧 Push,Pop時間為O(1)

用單鏈表實現棧 Push,Pop時間為O(1)

pri 時間 int 實現一個棧 我們 來看 一個棧 list() linked

  • 用單鏈表實現一個棧,要求Push Pop的運行時間為O(1),來自《算法導論》習題10.2-2。

    因為Push和Pop操作伴隨著棧頂元素的插入和刪除,所以,這個問題的本質是:在單鏈表的哪個位置進行插入和刪除,其運行時間為O(1)?初步來看,可能的選項有兩個,頭部和尾部。

    又因為,要想在單鏈表上插入和刪除某個元素,必須先知道它在鏈表中的前驅和後繼。如果選擇尾部,那麽我們需要一直維護尾部元素的前驅和後繼,後繼節點是固定的(通常是哨兵節點),但是前驅節點的變化的,沒辦法在常量時間內拿到,所以這個方案不可行。

    再來看,選擇頭部行不行呢?頭部節點的前驅是固定的,沒有問題,而它的後繼可以通過它的前驅索引到,時間是O(1)。所以我們選擇將單鏈表的頭部元素當做棧頂元素來實現這個棧。

    下面是C++實現,單鏈表采用的是帶哨兵的循環鏈表形式。節點鍵值類型簡化為int。

class StackByLinkedList
{
public:
    StackByLinkedList();
    ~StackByLinkedList();
    void Push(int key);
    void Pop();
    int  Top() const;
private:
    struct Node
    {
        Node* pNext;
        int key;
    };
    Node m_sentinel;
};

StackByLinkedList::StackByLinkedList()
{
    m_sentinel.pNext = &m_sentinel;
}

StackByLinkedList::~StackByLinkedList()
{
    Node* pCurrent = m_sentinel.pNext;
    Node* pNext = nullptr;
    while(pCurrent != &m_sentinel)
    {
        pNext = pCurrent->pNext;
        delete pCurrent;
        pCurrent = pNext;
    }
}

void StackByLinkedList::Push(int key)
{
    Node* pNew = new Node;
    pNew->key = key;
    pNew->pNext = m_sentinel.pNext;
    m_sentinel.pNext = pNew;
}

void StackByLinkedList::Pop()
{
    Node* pDelete = m_sentinel.pNext;
    if(pDelete == &m_sentinel)
        return;
    m_sentinel.pNext = pDelete->pNext;
    delete pDelete;
}

int StackByLinkedList::Top() const
{
    Node* pTop = m_sentinel.pNext;
    return pTop == &m_sentinel ? -1 : pTop->key;
}

用單鏈表實現棧 Push,Pop時間為O(1)