试试这个...
定义:
-
S.top 是指向堆栈顶部的某个 X 类型节点的指针
-
X 是一个有两个指针的节点,top 和 base
-
X.top 指向栈顶的下一个节点。
-
X.base 指向堆栈底部的下一个节点(底部)
首先初始化栈顶指针:
STACK-INITIAL:
S.top = NIL
return true // Never fails
空栈测试:
STACK-EMPTY:
return (S.top == NIL)
将节点x 推入堆栈:
PUSH(x):
x.top = NIL // Top of stack, therfore top is NIL
x.base = S.top // base is previous top
S.top = x // x is now top of stack
return true
弹出并返回栈顶(这是唯一“有趣”的部分):
POP():
x = S.top // Top node on stack (could be NIL)
if S.top != NIL // Check in case stack was empty
S.top = x.base // New top = next node toward base
x.base = NIL // Disconnect x from stack
if S.top != NIL // Is stack now empty?
S.top.top = NIL // No, set top node's top pointer to NIL
return x // x could be NIL if stack was empty
需要考虑的事情...我在上面使用了双链表,因为
看起来这就是你正在使用的。但是,您只需要一个
单链表,其中链接指向堆栈的底部。
请注意,上述算法中的x.top 指针几乎
无用(设置但从未引用)。只要您跟踪堆栈顶部(S.top)就可以了
您需要做的是在 POP 操作期间追溯堆栈。
对 cmets 的回应
当一个元素从栈中弹出时,它所有的关联
指针应设置为 NIL。这是因为它不再是一部分
堆栈的所以不应该指向任何堆栈元素。我加了一点
到我原来的答案(见上文)。
以类似的方式,新的栈顶元素(除非栈变空)
需要有它的指针指向它上面的元素
设置为 NIL(因为它上面的元素已被删除)。
在我的例子中,这就是S.top.top = NIL
东西都是关于(S.top 指向顶部堆栈元素,所以S.top.top 是
该元素的顶部指针)。我想你会对x.next.prev = NIL 做同样的事情,
假设 x 是您弹出的元素,而不是 NIL 本身。在您的伪代码中,它看起来
像x.next.prev = L.head 这样会使堆栈元素顶部的 prev 指针指向自身
因为L.head 被设置为x.next(之前的新栈顶)。
最后,我质疑为什么要使用双链表
实现一个栈,只有一个带有指针的链表
它下面的下一个元素是必需的