Generally, swaps rely on a third variable to store one of the values to be reversed. For instance, given list [3, 4, 1, 6, 5]
, swapping the first and the last can be accomplished like so:
l = [3, 4, 1, 6, 5]
_temp = l[0] #first value
l[0] = l[-1]
l[-1] = _temp
#[5, 4, 1, 6, 3]
The implementation below utilizes a default parameter that will store the reference to the first node in the list. Once the end of the list has been reached, the simple swap operation, similar to the swap above, will take place:
class LinkedList:
def __init__(self, head=None):
self.head = head
self._next = None
def insert_node(self, val):
if self.head is None:
self.head = val
else:
getattr(self._next, 'insert_node', lambda x:setattr(self, '_next', LinkedList(x)))(val)
def swap(self, first = None, count = 0):
if not self._next and self.head is not None:
_head = getattr(self, 'head')
if first:
self.head = getattr(first, 'head')
setattr(first, 'head', _head)
else:
if self.head:
self._next.swap(first = self if not count else first, count = 1)
@classmethod
def load_list(cls, length = 5):
_l = cls()
import random
for _ in range(length):
_l.insert_node(random.randint(1, 100))
return _l
def flatten(self):
if self.head is not None:
return [self.head, *getattr(self._next, 'flatten', lambda :'')()]
return ''
def __repr__(self):
return ', '.join(map(str, self.flatten()))
This simple recursion will work for lists of any size:
for i in range(10):
l = LinkedList.load_list(length = i)
_s = repr(l)
l.swap()
print(f'{_s} -> {repr(l)}')
Output:
->
14 -> 14
80, 57 -> 57, 80
83, 44, 80 -> 80, 44, 83
94, 10, 42, 81 -> 81, 10, 42, 94
25, 26, 32, 31, 55 -> 55, 26, 32, 31, 25
8, 25, 25, 84, 83, 49 -> 49, 25, 25, 84, 83, 8
19, 95, 3, 33, 4, 56, 33 -> 33, 95, 3, 33, 4, 56, 19
97, 92, 37, 100, 27, 24, 33, 17 -> 17, 92, 37, 100, 27, 24, 33, 97
72, 24, 56, 18, 9, 64, 82, 85, 97 -> 97, 24, 56, 18, 9, 64, 82, 85, 72