标签:算法 删除 插入 amp ptr ++ vat let ret
用单链表实现一个栈,要求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;
}
标签:算法 删除 插入 amp ptr ++ vat let ret
原文地址:https://www.cnblogs.com/meixiaogua/p/9692930.html