【问题标题】:Python Reverse a Linked ListPython反转链表
【发布时间】:2015-10-21 00:38:01
【问题描述】:

我正在做一个 Python 程序,它实现了链表来支持一些功能,我需要做的一个功能是反转堆栈。我已经制作了一个 Node、LinkedList 和 Stack 类,这是我目前的代码:

class ListNode:

    def __init__(self, Object):
        self.Object = Object
        self.next = None

class LinkedList:

    def __init__(self):
        self.head = None # first node
        self.tail = None # last node

    def addLast(self, Object):
        newNode = ListNode(Object)
        if self.head == None:
            self.head = newNode
            self.tail = newNode
        else:
           self.tail.next = newNode
           self.tail = newNode

    def removeFirst(self):
        if self.head == None:
            return

        self.head = self.head.next
        if self.head == None:
            self.tail = None

    def removeLast(self, Object):
        if self.head == None:
            return

        current = self.head
        prev = None
        while current.next != None:
            prev = current
            current = current.next

        if prev == None:
            self.head = None
            self.tail = None
        else:
            prev.next = None
            self.tail = prev

    def get(self, index):
        current = self.head
        i = 0
        while i < index and current != None:
            current = current.next
            i = i + 1
        if current != None and index >= 0:
            return current.Object
        else:
            return None

    def size(self):
        current = self.head
        count = 0
        while current != None:
            count = count + 1
            current = current.next
        return count

    def isEmpty(self):
        return self.head == None

    def printList(self):
        if self.head != None:
            current = self.head
            while current != None:
                print(current.Object, end = ' ')
                current = current.next
        print()

# -------------------- STACK ---------------------------------------------------
class Stack:
    # constructor implementation
    def __init__(self):
        self.llist = LinkedList()

    def front(self):
        return self.llist.get(0)

    def dequeue(self):
        self.llist.removeFirst()

    def queue(self, Object):
        self.llist(Object)

    def push(self, Object):
        self.llist.addLast(Object)

    def pop(self, Object):
        self.llist.removeLast(Object)

    def printStack(self):
        self.llist.printList()

    def size(self):
        return self.llist.size()

    def isEmpty(self):
        return self.llist.isEmpty()

# ----------------------- Reverse LIST ------------------------------
def Reverse(S):
    # S is a Stack Object

这是我对这个问题的尝试:

def rRecursive( self ) :
    self._rRecursive( self.head )

def _reverseRecursive( self, n ) :
    if None != n:
      right = n.next
      if self.head != n:
        n.next = self.head
        self.head = n
      else:
        n.next = None

      self._rRecursive( right )

def Reverse(S):
    s.rRecursive()

如果这是一个普通列表,我可以使用 [::-1] 轻松反转它,但我不能,因为链接列表是一个对象。我在想也许我可以使用临时值,这样我就可以将堆栈的开头附加到列表中,然后以某种方式将其转换回堆栈对象。

重复编辑:我的程序的目标是使用现有堆栈并将其反转。链接的帖子处理已经采用列表格式的链接列表。

def get(self, index):
        current = self.head
        i = 0
        while i < index and current != None:
            current = current.next
            i = i + 1
        if current != None and index >= 0:
            return current.Object
        else:
            return None

编辑 2:添加了我的 get 函数。

class Stack:
    # constructor implementation
    def __init__(self):
        self.llist = LinkedList()

    def front(self):
        return self.llist.get(0)

        # push method implementation
    def push(self, Object):
        self.llist.addLast(Object)

    def pop1(self):
        self.llist.removeLast1()

def Reverse(S): 
    new_stack = Stack()
    while not S.isEmpty():
        new_stack.push(S.front())
        S.pop1()
    return new_stack

# Current Stack after Push: 12 14 40 13
# Stack after Pop: 12 14 40
# Stack after Reversal: 12 12 12

编辑 3:添加了我的代码的返工,它一遍又一遍地返回与第一个元素的错误反转。

【问题讨论】:

  • 如果你实现了__getitem__,你可以用[::1]反转它并让它接受val作为slice。我猜这是你的家庭作业?
  • 是的,这是我的家庭作业,这是我需要做的最后一个功能。我已经编辑了我之前工作的获取项目功能的问题。我遇到的问题是我无法反转我的 Stack 因为它已经是一个 Stack 对象。

标签: python list linked-list


【解决方案1】:

使用基本的堆栈操作很容易反转堆栈。从旧堆栈中弹出每个项目并将其推送到新堆栈上。

def reverse(stack):
    new_stack = Stack()
    while not stack.isEmpty():
        new_stack.push(stack.front())
        stack.pop()
    return new_stack

在重用堆栈对象本身时,您可以执行类似于破坏性地反转 Stack 中的 LinkedList 的操作,您只需要使用列表操作而不是为其别名的堆栈操作。

谈到堆栈操作,您可能会发现如果从前面而不是从后面推送和弹出堆栈,您的堆栈性能会更好。从链表末尾删除一个项目需要遍历整个链表(以找到倒数第二个节点)。相比之下,从前面添加和删除都很快。

【讨论】:

  • 您好,Blck,感谢您花时间回答我的问题。我已经尝试过您的方法并且它在一定程度上有效,但是,我没有得到堆栈的反转,而只是元素列表的第一个元素重复。这是我的输出: 弹出后的堆栈:12 14 40 反转后的堆栈:12 12 12 我还再次更新了我的帖子,以显示代码 sn-p 中每个块的内容。
  • 哦,看起来你的堆栈有问题。您正在从最后推动和弹出,但您可以访问的唯一值是前面的值。正如我在问题中所建议的那样,您可能应该将 pushpop 更改为从前面工作,这将使逻辑在不修改 front 的情况下工作(尽管更改将是一个替代修复)。
  • 感谢 Blck 回复我,我将重新编写我的代码,以便我的 push 和 pop 可以从前面工作!
【解决方案2】:

您不必在反转函数中摆弄链接指针。我假设您的堆栈中有一个 pop() 方法和其他基础知识;如果没有,则克隆您的 removeFirst 函数以返回已删除的节点。

现在,递归函数很简单:弹出列表的头部,反转剩余的堆栈(如果有),并将弹出的节点添加到末尾。这能解决你的问题吗?

def reverseStack(self):
    move_me = self.pop()
    if not self.isEmpty():
        return (self.reverseStack()).addLast(move_me)
    else:
        new_stack = Stack()
        return new_stack.addLast(move_me)

【讨论】:

  • 我已经尝试过你的方法,但不幸的是,reverseStack() 没有在第一次返回中定义。
  • 这是未完成的代码粘贴到位;你需要适应并正确放置它。如果未定义,我怀疑您没有将其设为类方法。
  • 你说的很对,很抱歉让你回复我的错误。我将使用您的逻辑重新自己重新工作,并将其放入我的堆栈类方法中。感谢您的帮助。
【解决方案3】:

解决此问题的其他方法:作弊。

定义一个__iter__ 方法(在任何情况下都有意义;迭代是Python 的核心行为)以使您的类型可迭代。简单例子:

def __iter__(self):
    cur = self.head
    while cur is not None:
        yield cur.Object
        cur = cur.next

那就这样吧:

values = list(self)  # Creates a list containing the current set of values
self.head = self.tail = None  # Clear existing linked list
# Add back all the values in reverse order
for value in reversed(values):
    self.addLast(value)

当然,内存分配/释放开销的效率可能低于正确执行的效率。但效果可能微乎其微,而且大大简化了实现代码。

当然,正确地做到这一点并不难,只是稍微有点混乱(完全未经测试,但应该接近正确):

def reverse(self):
    # Start at beginning, which will be new end
    cur, last = self.head, None
    # Reverse head and tail pointers in advance
    self.head, self.tail = self.tail, self.head
    # Traverse while reversing direction of each node pointer
    while cur is not None:
        # Tuple pack and unpack allows one-line variable swap
        cur.next, cur, last = last, cur.next, cur

【讨论】:

    【解决方案4】:

    使用基本数据结构反转事物的常用算法是利用堆栈是先进后出数据结构这一事实。这意味着如果您 pop 直到堆栈为空,您将按照与 pushed 的相反顺序获得项目。

    但您似乎想通过递归函数而不是显式堆栈来执行此操作 - 在这种情况下,您的函数通常会获取最前面的元素,然后递归数据结构的其余部分, then 处理第一个元素。这将按顺序取出所有元素,但在每个递归调用完成时以相反的顺序处理它们,并且您可以按照自己的方式备份调用堆栈。如果您需要将元素添加到反转的数据结构中(而不仅仅是打印它们),您可以通过返回值来构建它,注意一旦您在当前元素之后的所有内容都反转了,您只需要附加该元素到前面,你得到的一切都是相反的。

    【讨论】:

      【解决方案5】:
      class Node(object):
          def __init__(self, data=None, next_node=None):
             self.data = data
             self.next = next_node
      
      
      def Reverse(head):
          if head == None :
              return None
          elif head.next == None :
              return head            # returns last element from stack
          else :
              temp = head.next       # stores next element while moving forward  
              head.next = None       # removes the forward link
              li = Reverse(temp)     # returns the last element
              temp.next = head       # now do the reverse link here
              return li
      
      def main() :
          temp4 = Node(4,None)
          temp3 = Node(3,temp4)
          temp2 = Node(2,temp3)
          head = Node(1,temp2)
          res = Reverse(head)
          while res != None :
              print(res.data)
              res = res.next
      main()
      

      【讨论】:

      • 如果您的答案包含 cmets 或更多关于您的答案如何解决问题的描述,那么您的答案可能会更有帮助。
      • 代码递归地将列表放入堆栈,然后从最后一个元素开始向后链接。那就是我使用返回头,从堆栈中返回最后一个元素并将其用作头。 temp 变量用于存储列表中的下一个元素,这是因为我们必须删除前向链接,并且需要将下一个元素放入堆栈。
      猜你喜欢
      • 2014-02-27
      • 1970-01-01
      • 1970-01-01
      • 2013-02-15
      • 1970-01-01
      • 2021-05-21
      • 2016-09-29
      相关资源
      最近更新 更多