用单链表实现栈 Push,Pop时间为O

Posted meixiaogua

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用单链表实现栈 Push,Pop时间为O相关的知识,希望对你有一定的参考价值。

  • 用单链表实现一个栈,要求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的主要内容,如果未能解决你的问题,请参考以下文章

实现一个栈,Push,Pop,Min,并且保证时间复杂度为O

单链表与栈

基于单链表实现一个非阻塞的栈

日常学习随笔-数组单链表双链表三种形式实现栈结构的基本操作

算法:用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。《剑指offer》

实现一个队列,使得push_rear(), pop_front() 和get_min()的时间复杂度为O