Skip to content

Commit c57c4ca

Browse files
onlinejudge95cclauss
authored andcommitted
Adds operations for circular linked list (#1584)
* Adds, append, len, print operations for circular linked list * Adds, prepend support * Adds, delete from front of the list * Adds, delete_rear support * Adds, method documentations * Adds, type checking and doctests * Updates doctest for delete ops * Addressing requested changes * Removes unused import * Fixes failing doctests * Minor modifications...
1 parent 2565797 commit c57c4ca

File tree

1 file changed

+186
-0
lines changed

1 file changed

+186
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
from typing import Any
2+
3+
4+
class Node:
5+
"""
6+
Class to represent a single node.
7+
8+
Each node has following attributes
9+
* data
10+
* next_ptr
11+
"""
12+
13+
def __init__(self, data: Any):
14+
self.data = data
15+
self.next_ptr = None
16+
17+
18+
class CircularLinkedList:
19+
"""
20+
Class to represent the CircularLinkedList.
21+
22+
CircularLinkedList has following attributes.
23+
* head
24+
* length
25+
"""
26+
27+
def __init__(self):
28+
self.head = None
29+
self.length = 0
30+
31+
def __len__(self) -> int:
32+
"""
33+
Dunder method to return length of the CircularLinkedList
34+
>>> cll = CircularLinkedList()
35+
>>> len(cll)
36+
0
37+
>>> cll.append(1)
38+
>>> len(cll)
39+
1
40+
"""
41+
return self.length
42+
43+
def __str__(self) -> str:
44+
"""
45+
Dunder method to represent the string representation of the CircularLinkedList
46+
>>> cll = CircularLinkedList()
47+
>>> print(cll)
48+
Empty linked list
49+
>>> cll.append(1)
50+
>>> cll.append(2)
51+
>>> print(cll)
52+
<Node data=1> => <Node data=2>
53+
"""
54+
current_node = self.head
55+
if not current_node:
56+
return "Empty linked list"
57+
58+
results = [current_node.data]
59+
current_node = current_node.next_ptr
60+
61+
while current_node != self.head:
62+
results.append(current_node.data)
63+
current_node = current_node.next_ptr
64+
65+
return " => ".join(f"<Node data={result}>" for result in results)
66+
67+
def append(self, data: Any) -> None:
68+
"""
69+
Adds a node with given data to the end of the CircularLinkedList
70+
>>> cll = CircularLinkedList()
71+
>>> cll.append(1)
72+
>>> print(f"{len(cll)}: {cll}")
73+
1: <Node data=1>
74+
>>> cll.append(2)
75+
>>> print(f"{len(cll)}: {cll}")
76+
2: <Node data=1> => <Node data=2>
77+
"""
78+
current_node = self.head
79+
80+
new_node = Node(data)
81+
new_node.next_ptr = new_node
82+
83+
if current_node:
84+
while current_node.next_ptr != self.head:
85+
current_node = current_node.next_ptr
86+
87+
current_node.next_ptr = new_node
88+
new_node.next_ptr = self.head
89+
else:
90+
self.head = new_node
91+
92+
self.length += 1
93+
94+
def prepend(self, data: Any) -> None:
95+
"""
96+
Adds a ndoe with given data to the front of the CircularLinkedList
97+
>>> cll = CircularLinkedList()
98+
>>> cll.prepend(1)
99+
>>> cll.prepend(2)
100+
>>> print(f"{len(cll)}: {cll}")
101+
2: <Node data=2> => <Node data=1>
102+
"""
103+
current_node = self.head
104+
105+
new_node = Node(data)
106+
new_node.next_ptr = new_node
107+
108+
if current_node:
109+
while current_node.next_ptr != self.head:
110+
current_node = current_node.next_ptr
111+
112+
current_node.next_ptr = new_node
113+
new_node.next_ptr = self.head
114+
115+
self.head = new_node
116+
self.length += 1
117+
118+
def delete_front(self) -> None:
119+
"""
120+
Removes the 1st node from the CircularLinkedList
121+
>>> cll = CircularLinkedList()
122+
>>> cll.delete_front()
123+
Traceback (most recent call last):
124+
...
125+
IndexError: Deleting from an empty list
126+
>>> cll.append(1)
127+
>>> cll.append(2)
128+
>>> print(f"{len(cll)}: {cll}")
129+
2: <Node data=1> => <Node data=2>
130+
>>> cll.delete_front()
131+
>>> print(f"{len(cll)}: {cll}")
132+
1: <Node data=2>
133+
"""
134+
if not self.head:
135+
raise IndexError("Deleting from an empty list")
136+
137+
current_node = self.head
138+
139+
if current_node.next_ptr == current_node:
140+
self.head, self.length = None, 0
141+
else:
142+
while current_node.next_ptr != self.head:
143+
current_node = current_node.next_ptr
144+
145+
current_node.next_ptr = self.head.next_ptr
146+
self.head = self.head.next_ptr
147+
148+
self.length -= 1
149+
150+
def delete_rear(self) -> None:
151+
"""
152+
Removes the last node from the CircularLinkedList
153+
>>> cll = CircularLinkedList()
154+
>>> cll.delete_rear()
155+
Traceback (most recent call last):
156+
...
157+
IndexError: Deleting from an empty list
158+
>>> cll.append(1)
159+
>>> cll.append(2)
160+
>>> print(f"{len(cll)}: {cll}")
161+
2: <Node data=1> => <Node data=2>
162+
>>> cll.delete_rear()
163+
>>> print(f"{len(cll)}: {cll}")
164+
1: <Node data=1>
165+
"""
166+
if not self.head:
167+
raise IndexError("Deleting from an empty list")
168+
169+
temp_node, current_node = self.head, self.head
170+
171+
if current_node.next_ptr == current_node:
172+
self.head, self.length = None, 0
173+
else:
174+
while current_node.next_ptr != self.head:
175+
temp_node = current_node
176+
current_node = current_node.next_ptr
177+
178+
temp_node.next_ptr = current_node.next_ptr
179+
180+
self.length -= 1
181+
182+
183+
if __name__ == "__main__":
184+
import doctest
185+
186+
doctest.testmod()

0 commit comments

Comments
 (0)