【问题标题】:Linked List implementation for a stack堆栈的链表实现
【发布时间】:2013-03-17 13:49:09
【问题描述】:

这是我用链表实现的堆栈

STACK using linked list 

STACK-EMPTY:
if L.head == NIL
    return True
else return False

PUSH(x):
x.next = L.head 
if L.head != NIL
    L.head.prev = x
L.head = x
x.prev = NIL

POP():
x = L.head
L.head = x.next
x.next.prev = L.head
return x

你会验证这个吗?如何改进?

谢谢

【问题讨论】:

  • 您为此使用双链表有什么特别的原因吗?您可以使用单链表实现堆栈,因为不需要 prev 指针。
  • 似乎是 codereview.SE 的问题
  • 谢谢不知道

标签: algorithm linked-list stack doubly-linked-list


【解决方案1】:

您可以提高数据结构的一致性:

  1. 列表头的prev总是NIL
  2. 不在列表中的元素将 nextprev 设置为 NIL

考虑到 1. 考虑到您的 POP 存在不一致,这可能是错误的来源:当您弹出一个元素时,头部的 prev 是头部本身,当您推送一个元素时,头部的 prev 是无。

【讨论】:

    【解决方案2】:

    试试这个...

    定义:

    • S.top 是指向堆栈顶部的某个 X 类型节点的指针
    • X 是一个有两个指针的节点,topbase
    • 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 操作期间追溯堆栈。

    对 cme​​ts 的回应

    当一个元素从栈中弹出时,它所有的关联 指针应设置为 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(之前的新栈顶)。

    最后,我质疑为什么要使用双链表 实现一个栈,只有一个带有指针的链表 它下面的下一个元素是必需的

    【讨论】:

    • 在我的伪代码中,L.head 指向堆栈中的第一个元素,因此x.next = L.head 归结为x.base = S.top L.head = x 相当于你的S.top = x 然后x.top = NIL 是我的x.prev = NIL,我可以把它放在最后,对吧?
    • 但我认为我还需要使用我的if L.head != NIL L.head.prev = x 为堆栈中的前一个第一个元素制作 prev(顶部)指针以指向 x。所以:你能确认我的代码是正确的吗,并且,这最后一条语句在 PUSH() 方法中不是强制性的吗?非常感谢
    • 以同样的方式,不是 x.next.prev = L.head 对 POP() 是强制性的吗?谢谢
    • @macscholes 请参阅回答中对评论的回复
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-28
    • 2012-05-24
    相关资源
    最近更新 更多