Skip to content

Commit ecac7b0

Browse files
kanthuccclauss
andauthored
Contains loops.py add (TheAlgorithms#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>
1 parent dc415ec commit ecac7b0

File tree

1 file changed

+60
-0
lines changed

1 file changed

+60
-0
lines changed
+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
from typing import Any
2+
3+
4+
class ContainsLoopError(Exception):
5+
pass
6+
7+
8+
class Node:
9+
def __init__(self, data: Any) -> None:
10+
self.data = data
11+
self.next_node = None
12+
13+
def __iter__(self):
14+
node = self
15+
visited = []
16+
while node:
17+
if node in visited:
18+
raise ContainsLoopError
19+
visited.append(node)
20+
yield node.data
21+
node = node.next_node
22+
23+
@property
24+
def has_loop(self) -> bool:
25+
"""
26+
A loop is when the exact same Node appears more than once in a linked list.
27+
>>> root_node = Node(1)
28+
>>> root_node.next_node = Node(2)
29+
>>> root_node.next_node.next_node = Node(3)
30+
>>> root_node.next_node.next_node.next_node = Node(4)
31+
>>> root_node.has_loop
32+
False
33+
>>> root_node.next_node.next_node.next_node = root_node.next_node
34+
>>> root_node.has_loop
35+
True
36+
"""
37+
try:
38+
list(self)
39+
return False
40+
except ContainsLoopError:
41+
return True
42+
43+
44+
if __name__ == "__main__":
45+
root_node = Node(1)
46+
root_node.next_node = Node(2)
47+
root_node.next_node.next_node = Node(3)
48+
root_node.next_node.next_node.next_node = Node(4)
49+
print(root_node.has_loop) # False
50+
root_node.next_node.next_node.next_node = root_node.next_node
51+
print(root_node.has_loop) # True
52+
53+
root_node = Node(5)
54+
root_node.next_node = Node(6)
55+
root_node.next_node.next_node = Node(5)
56+
root_node.next_node.next_node.next_node = Node(6)
57+
print(root_node.has_loop) # False
58+
59+
root_node = Node(1)
60+
print(root_node.has_loop) # False

0 commit comments

Comments
 (0)