How to detect a loop in a linked list
Loop in a linked list
A linked list is a commonly used data structure made up of nodes that are interlinked using pointers.
Note: You can read more on a linked list here.
A linked list may contain a loop if a node points to another node that comes earlier in the chain. If this happens, an endless loop is created in the list.
Detecting a loop
A loop in a linked list can be detected in multiple ways. We may either use a dictionary or a map to detect a loop. We can also detect a loop using Floyd's Cycle-Detection Algorithm.
Floyd's cycle detection algorithm
In this algorithm, we use two pointers that traverse through the list. One moves one step at a time while the other moves two steps at a time. If we encounter the end of the list, there is no loop, but if the two pointers meet at some node, there is a loop in the list.
Code
class LinkedList:def __init__(self):self.root = Nonedef detectLoop(self):slow = self.rootfast = self.rootwhile fast.after and fast.after.after:fast = fast.after.afterslow = slow.afterif slow == fast:return Truereturn Falsemy_list1 = LinkedList()my_list1.root = Node(3)my_list1.root.after = Node(9)my_list1.root.after.after = Node(13)my_list1.root.after.after.after = Node(12)my_list1.root.after.after.after.after = Node(8)my_list1.root.after.after.after.after.after = Node(15)my_list1.root.after.after.after.after.after.after = my_list1.root.after.afterprint("List 1", "has" if my_list1.detectLoop() else "does not have", "a loop.")my_list2 = LinkedList()my_list2.root = Node(7)my_list2.root.after = Node(3)my_list2.root.after.after = Node(8)print("List 2", "has" if my_list2.detectLoop() else "does not have", "a loop.")
Explanation
Lines 5–13: Two variables
slowandfastiterate through the list. The variablefastmoves two steps whileslowmoves one step. If they point at the same node at any point, there is a loop. Otherwise, if they reachNone, there is no loop in the list.Lines 15–29: We create two linked lists, one with a loop and the other without one, and call the
detectLoop()function on them.
Using a dictionary
We can also use a dictionary to detect a loop in a linked list. We can do this by adding the nodes as keys in a dictionary. Should we encounter a key twice, we would know that the list contains a loop.
Code
class LinkedList:def __init__(self):self.root = Nonedef detectLoop(self):visited_nodes = dict()curr = self.rootvisited_nodes[curr] = Truewhile curr.after:try:if visited_nodes[curr.after]:return Trueexcept:visited_nodes[curr.after] = Truecurr = curr.afterreturn Falsemy_list1 = LinkedList()my_list1.root = Node(3)my_list1.root.after = Node(9)my_list1.root.after.after = Node(13)my_list1.root.after.after.after = Node(12)my_list1.root.after.after.after.after = Node(8)my_list1.root.after.after.after.after.after = Node(15)my_list1.root.after.after.after.after.after.after = my_list1.root.after.afterprint("List 1", "has" if my_list1.detectLoop() else "does not have", "a loop.")my_list2 = LinkedList()my_list2.root = Node(7)my_list2.root.after = Node(3)my_list2.root.after.after = Node(8)print("List 2", "has" if my_list2.detectLoop() else "does not have", "a loop.")
Explanation
Lines 6–8: We create a dictionary that stores the addresses of nodes we have already visited and sets the value to
True.Lines 10–12: The
tryblock checks if a node already exists invisited_nodesand returnsTrue.Lines 13–15: The
exceptblock adds a node to the dictionary and updates the value ofcurrto move through the list.Line 16: If the
whileloop encounters aNonenode, it exits the loop, and the function returnsTrue.Lines 18–32: We create two linked lists and call the function
detectLoop(), which checks if there's a loop in the linked list.
Note: You can read about removing a loop in a linked list here.
Free Resources