简体   繁体   English

Python反向链接列表

[英]Python Reverse a Linked List

I am doing a Python program that implements linked list to support a few functions, one of the functions I need to do is to reverse a stack. 我正在做一个实现链接列表以支持一些功能的Python程序,我需要做的功能之一就是反转堆栈。 I have made a Node, LinkedList and Stack classes, here is my Code so far: 我已经制作了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

Here is my attempt at the problem: 这是我尝试解决的问题:

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()

If this was an ordinary list I could easily reverse it using [::-1] but I cannot since the linkedlist is an object. 如果这是一个普通列表,我可以使用[::-1]轻松地将其反转,但是由于链表是一个对象,所以我不能。 I was thinking maybe I could use temporary values so I can someone append the beginning of the stack to a list and then somehow convert it back into a stack object. 我在想也许可以使用临时值,以便有人可以将堆栈的开头附加到列表中,然后以某种方式将其转换回堆栈对象。

Edit for duplication : The goal of my program is use an existing Stack and reverse it. 编辑重复项 :我的程序的目标是使用现有的Stack并反转它。 The linked post deals with a linked list that was already in a list format. 链接的帖子处理的链接列表已经是列表格式。

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

Edit 2 : added my get function. 编辑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

Edit 3 : Added a rework of my code, it returns back a wrong reversal with the first element over and over again. 编辑3 :添加了我的代码的返工,它返回错误的反转,第一个元素一遍又一遍。

It's quite easy to reverse a stack using basic stack operations. 使用基本堆栈操作来反转堆栈非常容易。 Pop each item off the old stack and push it onto a new one. 从旧堆栈中弹出每个项目,然后将其推入新的项目。

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

You could do something similar to destructively reverse the LinkedList within the Stack while reusing the stack object itself, you'd just need to use the list operations rather than the stack operations that are aliased to them. 您可以执行类似的操作,在重新使用堆栈对象本身的同时,破坏性地反转StackLinkedList ,您只需要使用列表操作,而不是使用别名的堆栈操作。

Speaking of stack operations, you'll probably find that your stack performs better if you push and pop from the front, rather than the back. 说到堆栈操作,您可能会发现,如果从正面而不是背面推动和弹出,堆栈的性能会更好。 Removing an item from the end of the linked list requires iterating over the whole list (to find the next-to-last node). 从链接列表的末尾删除项目需要遍历整个列表(以找到倒数第二个节点)。 In contrast, both adding and removing from the front are fast. 相反,从前面添加和删除都很快。

You shouldn't have to fiddle with link pointers in your reversal function. 您不必在反转函数中摆弄链接指针。 I assume that you have a pop() method and other basics with your stack; 我假设您的堆栈中有pop()方法和其他基础知识; if not, then clone your removeFirst function to return the removed node. 如果不是,则克隆您的removeFirst函数以返回已删除的节点。

Now, the recursive function is simple: pop the head of the list, reverse the remaining stack (if any), and add the popped node to the end. 现在,递归功能很简单:弹出列表的开头,反转剩余的堆栈(如果有),然后将弹出的节点添加到末尾。 Does this handle your problem? 这样可以解决您的问题吗?

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)

Other approaches to solving this problem: Cheat. 解决此问题的其他方法:作弊。

Define a __iter__ method (which makes sense in any event; iteration is a core Python behavior) to make your type iterable. 定义__iter__方法(在任何情况下都有意义;迭代是Python的核心行为),以使您的类型可迭代。 Simple example: 简单的例子:

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

Then just do: 然后做:

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)

Sure, it's likely less efficient in memory allocation/deallocation overhead than doing it properly. 当然,在内存分配/重新分配开销方面,效率可能不如适当地低。 But the effect is likely marginal, and it simplifies the implementation code dramatically. 但是效果可能很小,并且极大地简化了实现代码。

Of course, doing it properly isn't that hard, it's just slightly more confusing (totally untested, but it should be close to right): 当然,正确地进行操作并不难,只是有些混乱(完全未经测试,但应该接近正确):

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

The usual algorithm for reversing things using basic data structures is to use the fact that a stack is a first in last out data structure. 使用基本数据结构反转事物的常用算法是利用堆栈是先进先出数据结构的事实。 That means if you pop until the stack is empty, you will get the items in the opposite order you push ed them on. 这意味着,如果您pop直到堆叠为空,您将以与push它们相反的顺序获得它们。

But it looks like you want to do this via recursive functions rather than an explicit stack - in this case, your function would normally fetch the front element, then recurse on the rest of the data structure, then handle that first element. 但是看起来您想通过递归函数而不是显式堆栈来执行此操作-在这种情况下,您的函数通常会获取front元素, 然后对其余数据结构进行递归, 然后处理该第一个元素。 This gets all the elements off in order, but handles them in the opposite order as each recursive call finishes and you work your way back up the call stack. 这样可以使所有元素按顺序排列,但是在每次递归调用完成时,您将以相反的顺序处理它们,然后按自己的方式备份调用堆栈。 If you neex to add the elements to a reversed data structure (and not just print them), you can build it up via return values by noticing that once you have the reverse if everything after the current element, you just need to attach that element to the front and you have the reverse of everything you were handed. 如果您需要将元素添加到反向数据结构中(而不仅仅是打印它们),则可以通过返回值来构建它,方法是:如果当前元素之后的所有内容都具有反向属性,则只需附加该元素到最前面,您所拥有的一切都与您相反。

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()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM