Skip to content

Commit c809e84

Browse files
New doubly linkedlist PR: pull/2573 (TheAlgorithms#3380)
TheAlgorithms#2573 the second implementation of the Doubly linked list
1 parent 1420665 commit c809e84

File tree

1 file changed

+253
-0
lines changed

1 file changed

+253
-0
lines changed
+253
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
"""
2+
- A linked list is similar to an array, it holds values. However, links in a linked
3+
list do not have indexes.
4+
- This is an example of a double ended, doubly linked list.
5+
- Each link references the next link and the previous one.
6+
- A Doubly Linked List (DLL) contains an extra pointer, typically called previous
7+
pointer, together with next pointer and data which are there in singly linked list.
8+
- Advantages over SLL - It can be traversed in both forward and backward direction.
9+
Delete operation is more efficient
10+
"""
11+
12+
13+
class Node:
14+
def __init__(self, data: int, previous=None, next_node=None):
15+
self.data = data
16+
self.previous = previous
17+
self.next = next_node
18+
19+
def __str__(self) -> str:
20+
return f"{self.data}"
21+
22+
def get_data(self) -> int:
23+
return self.data
24+
25+
def get_next(self):
26+
return self.next
27+
28+
def get_previous(self):
29+
return self.previous
30+
31+
32+
class LinkedListIterator:
33+
def __init__(self, head):
34+
self.current = head
35+
36+
def __iter__(self):
37+
return self
38+
39+
def __next__(self):
40+
if not self.current:
41+
raise StopIteration
42+
else:
43+
value = self.current.get_data()
44+
self.current = self.current.get_next()
45+
return value
46+
47+
48+
class LinkedList:
49+
def __init__(self):
50+
self.head = None # First node in list
51+
self.tail = None # Last node in list
52+
53+
def __str__(self):
54+
current = self.head
55+
nodes = []
56+
while current is not None:
57+
nodes.append(current.get_data())
58+
current = current.get_next()
59+
return " ".join(str(node) for node in nodes)
60+
61+
def __contains__(self, value: int):
62+
current = self.head
63+
while current:
64+
if current.get_data() == value:
65+
return True
66+
current = current.get_next()
67+
return False
68+
69+
def __iter__(self):
70+
return LinkedListIterator(self.head)
71+
72+
def get_head_data(self):
73+
if self.head:
74+
return self.head.get_data()
75+
return None
76+
77+
def get_tail_data(self):
78+
if self.tail:
79+
return self.tail.get_data()
80+
return None
81+
82+
def set_head(self, node: Node) -> None:
83+
84+
if self.head is None:
85+
self.head = node
86+
self.tail = node
87+
else:
88+
self.insert_before_node(self.head, node)
89+
90+
def set_tail(self, node: Node) -> None:
91+
if self.head is None:
92+
self.set_head(node)
93+
else:
94+
self.insert_after_node(self.tail, node)
95+
96+
def insert(self, value: int) -> None:
97+
node = Node(value)
98+
if self.head is None:
99+
self.set_head(node)
100+
else:
101+
self.set_tail(node)
102+
103+
def insert_before_node(self, node: Node, node_to_insert: Node) -> None:
104+
node_to_insert.next = node
105+
node_to_insert.previous = node.previous
106+
107+
if node.get_previous() is None:
108+
self.head = node_to_insert
109+
else:
110+
node.previous.next = node_to_insert
111+
112+
node.previous = node_to_insert
113+
114+
def insert_after_node(self, node: Node, node_to_insert: Node) -> None:
115+
node_to_insert.previous = node
116+
node_to_insert.next = node.next
117+
118+
if node.get_next() is None:
119+
self.tail = node_to_insert
120+
else:
121+
node.next.previous = node_to_insert
122+
123+
node.next = node_to_insert
124+
125+
def insert_at_position(self, position: int, value: int) -> None:
126+
current_position = 1
127+
new_node = Node(value)
128+
node = self.head
129+
while node:
130+
if current_position == position:
131+
self.insert_before_node(node, new_node)
132+
return None
133+
current_position += 1
134+
node = node.next
135+
self.insert_after_node(self.tail, new_node)
136+
137+
def get_node(self, item: int) -> Node:
138+
node = self.head
139+
while node:
140+
if node.get_data() == item:
141+
return node
142+
node = node.get_next()
143+
raise Exception("Node not found")
144+
145+
def delete_value(self, value):
146+
node = self.get_node(value)
147+
148+
if node is not None:
149+
if node == self.head:
150+
self.head = self.head.get_next()
151+
152+
if node == self.tail:
153+
self.tail = self.tail.get_previous()
154+
155+
self.remove_node_pointers(node)
156+
157+
@staticmethod
158+
def remove_node_pointers(node: Node) -> None:
159+
if node.get_next():
160+
node.next.previous = node.previous
161+
162+
if node.get_previous():
163+
node.previous.next = node.next
164+
165+
node.next = None
166+
node.previous = None
167+
168+
def is_empty(self):
169+
return self.head is None
170+
171+
172+
def create_linked_list() -> None:
173+
"""
174+
>>> new_linked_list = LinkedList()
175+
>>> new_linked_list.get_head_data() is None
176+
True
177+
>>> new_linked_list.get_tail_data() is None
178+
True
179+
>>> new_linked_list.is_empty()
180+
True
181+
>>> new_linked_list.insert(10)
182+
>>> new_linked_list.get_head_data()
183+
10
184+
>>> new_linked_list.get_tail_data()
185+
10
186+
>>> new_linked_list.insert_at_position(position=3, value=20)
187+
>>> new_linked_list.get_head_data()
188+
10
189+
>>> new_linked_list.get_tail_data()
190+
20
191+
>>> new_linked_list.set_head(Node(1000))
192+
>>> new_linked_list.get_head_data()
193+
1000
194+
>>> new_linked_list.get_tail_data()
195+
20
196+
>>> new_linked_list.set_tail(Node(2000))
197+
>>> new_linked_list.get_head_data()
198+
1000
199+
>>> new_linked_list.get_tail_data()
200+
2000
201+
>>> for value in new_linked_list:
202+
... print(value)
203+
1000
204+
10
205+
20
206+
2000
207+
>>> new_linked_list.is_empty()
208+
False
209+
>>> for value in new_linked_list:
210+
... print(value)
211+
1000
212+
10
213+
20
214+
2000
215+
>>> 10 in new_linked_list
216+
True
217+
>>> new_linked_list.delete_value(value=10)
218+
>>> 10 in new_linked_list
219+
False
220+
>>> new_linked_list.delete_value(value=2000)
221+
>>> new_linked_list.get_tail_data()
222+
20
223+
>>> new_linked_list.delete_value(value=1000)
224+
>>> new_linked_list.get_tail_data()
225+
20
226+
>>> new_linked_list.get_head_data()
227+
20
228+
>>> for value in new_linked_list:
229+
... print(value)
230+
20
231+
>>> new_linked_list.delete_value(value=20)
232+
>>> for value in new_linked_list:
233+
... print(value)
234+
>>> for value in range(1,10):
235+
... new_linked_list.insert(value=value)
236+
>>> for value in new_linked_list:
237+
... print(value)
238+
1
239+
2
240+
3
241+
4
242+
5
243+
6
244+
7
245+
8
246+
9
247+
"""
248+
249+
250+
if __name__ == "__main__":
251+
import doctest
252+
253+
doctest.testmod()

0 commit comments

Comments
 (0)