Python/data_structures/linked_list/has_loop.py
kanthuc ecac7b0973
Contains loops.py add (#2442)
* added an algorithm which checks a linked list for loops and returns true if one is found

* added doctests and clarified meaning of loop

* Define Node.__iter__()

* Update and rename has_loop.py to has_duplicate_data.py

* Update has_duplicate_data.py

* Update has_duplicate_data.py

* Update and rename has_duplicate_data.py to has_loop.py

* Update has_loop.py

Co-authored-by: Christian Clauss <cclauss@me.com>
2020-09-18 22:53:50 +02:00

61 lines
1.6 KiB
Python

from typing import Any
class ContainsLoopError(Exception):
pass
class Node:
def __init__(self, data: Any) -> None:
self.data = data
self.next_node = None
def __iter__(self):
node = self
visited = []
while node:
if node in visited:
raise ContainsLoopError
visited.append(node)
yield node.data
node = node.next_node
@property
def has_loop(self) -> bool:
"""
A loop is when the exact same Node appears more than once in a linked list.
>>> root_node = Node(1)
>>> root_node.next_node = Node(2)
>>> root_node.next_node.next_node = Node(3)
>>> root_node.next_node.next_node.next_node = Node(4)
>>> root_node.has_loop
False
>>> root_node.next_node.next_node.next_node = root_node.next_node
>>> root_node.has_loop
True
"""
try:
list(self)
return False
except ContainsLoopError:
return True
if __name__ == "__main__":
root_node = Node(1)
root_node.next_node = Node(2)
root_node.next_node.next_node = Node(3)
root_node.next_node.next_node.next_node = Node(4)
print(root_node.has_loop) # False
root_node.next_node.next_node.next_node = root_node.next_node
print(root_node.has_loop) # True
root_node = Node(5)
root_node.next_node = Node(6)
root_node.next_node.next_node = Node(5)
root_node.next_node.next_node.next_node = Node(6)
print(root_node.has_loop) # False
root_node = Node(1)
print(root_node.has_loop) # False