Search code examples
pythonalgorithmsingly-linked-list

Reverse a singly-Linked List without changing the orginal LinkedList


I've have two .py files.

  1. LinkedList.py which holds a custom-built Node class.
  2. script.py which contains my code to reverse the LinkedList

I'm importing the Node class like so in the script.py:
from LinkedList import *
I've made a function named reverse_linked_list in script.py which holds a parameter named linked_list.

I'm able to reverse the linked_list like so:

def reverse_linked_list(linked_list):
  prev = None
  current = Node(linked_list).data
  while (current is not None):
    nextNode = current.next
    current.next = prev
    prev = current
    current = nextNode
  current = prev
  return prev

I've been handed some objects to work with

print("Original")
demo_list = make_linked_list([4,8,15])
demo_list.print_linked_list()
print("Reversed")
reverse = reverse_linked_list(demo_list)
reverse.print_linked_list()
print("Original Unchanged")
demo_list.print_linked_list()

The implementation of the Node class look like this:

class Node:
  def __init__(self, data, next_node=None):
    self.data = data
    self.next = next_node

I'm trying to understand why my code is changing the "original list" but can't figure out why. The output I'm getting is:

Original
4
8
15
Reversed
15
8
4
Original Unchanged
4

I want that "Original Unchanged" dont get changed and stay as "Original". where does the original list getting changed and why?


Solution

  • Here are the functions/methods that will make the driver code work as expected:

    class Node:
        def __init__(self, data, next_node=None):
            self.data = data
            self.next = next_node
    
        def __iter__(self):
            node = self
            while node:
                yield node.data
                node = node.next
    
        def __repr__(self):
            return "->".join(map(repr, self))
        
        def print_linked_list(self):
            print(self)
    
    
    def reverse_linked_list(iterable):
        revhead = None
        for data in iterable:
            revhead = Node(data, revhead)
        return revhead
    
    def make_linked_list(values):
        return reverse_linked_list(reversed(values))
    

    Note that reverse_linked_list is able to create a linked list from not only another linked list, but any iterable. This is because a Node instance is made iterable by implementing the __iter__ method.

    Here is your driver code, with the output it will generate:

    print("Original")
    demo_list = make_linked_list([4,8,15])
    demo_list.print_linked_list()
    print("Reversed")
    reverse = reverse_linked_list(demo_list)
    reverse.print_linked_list()
    print("Original Unchanged")
    demo_list.print_linked_list()
    

    Output:

    Original
    4->8->15
    Reversed
    15->8->4
    Original Unchanged
    4->8->15