简体   繁体   中英

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. I have made a Node, LinkedList and Stack classes, here is my Code so far:

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. 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. 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.

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.

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.

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; if not, then clone your removeFirst function to return the removed node.

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. 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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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