Reversing a Linked List: the sane way, the recursive way and the push way

Reversing a SLL takes O(N). You can reverse a doubly linked list in O(1) if you swap head and tail and you’re ok with going backwards with next and vice versa.

The sane and obvious way is to use three pointers (back, middle and front); you make the middle point to back, and shift everything one step right until front is None.

def bmfReverse(self):
    back = None
    middle = self.head
    front = middle.next

    while True:
        middle.next = back
        if front is None: break
        # advance the three pointers
        back = middle
        middle = front
        front = front.next

    self.head = middle

It is easy to turn this into a recursive function.

def recBmf(self, back=None, middle=None, front=None):
    # setup
    if middle is None: middle = self.head
    if front is None: front = middle.next

    middle.next = back

    # base case
    if front is None: 
        self.head = middle
        return
    return self.recBmf(middle, front, front.next)        

Finally, that’s the push-reverse strategy. It’s fucked up weird to read, but the idea is actually pretty simple: you keep pushing the front node (current) on the new result list, and as a last step you update the head pointer. Source: http://cslibrary.stanford.edu/105/LinkedListProblems.pdf

def pushReverse(self):
    result = None
    current = self.head
        
    while current is not None:
        # save the next node
        next = current.next

        # move the node onto result
        current.next = result
        result = current

        # update current
        current = next

    self.head = result

Bonus: reversing a doubly linked list

Oh Python, it’s not even fun this way!

def reverse(self):
    n = self.head
    while n is not None:
        n.next, n.prev = n.prev, n.next
        n = n.prev
    self.head, self.tail = self.tail, self.head