-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy pathdoubly_linked_list.py
136 lines (111 loc) · 3.77 KB
/
doubly_linked_list.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
from typing import Any
class Node:
data: Any
prev: "Node"
next: "Node"
def __init__(self, data) -> None:
self.data = data
self.next = None # type: ignore
self.prev = None # type: ignore
def push(self, node: "Node"):
if self.length > 1:
self.next.push(node)
else:
self.next = node
def pop(self):
match self.length:
case 1:
return None
case 2:
popped = self.next
self.next = None # type: ignore
return popped
case _:
return self.next.pop()
@property
def length(self):
if self.next is not None:
return 1 + self.next.length
return 1
def __str__(self) -> str:
if self.length > 1:
return f"Node({self.data}) <-> {self.next}"
else:
return f"Node({self.data})"
def __repr__(self) -> str:
return self.__str__()
class DoublyLinkedList:
head: Node
tail: Node
def __init__(self, head: Node) -> None:
self.head = head
self.tail = self.head
@property
def length(self):
if self.head is not None:
return self.head.length
return 0
def push_head(self, node: Node):
if self.head is None:
self.head = node
self.tail = node
else:
new_head = node
new_head.next = self.head
self.head.prev = new_head
self.head = new_head
def push_tail(self, node: Node):
if self.tail is None:
self.head = node
self.tail = node
else:
new_tail = node
new_tail.prev = self.tail
self.tail.next = new_tail
self.tail = new_tail
def pop_head(self):
if self.head:
popped = self.head
if self.tail == self.head:
self.head = None # type: ignore
self.tail = None # type: ignore
else:
self.head = self.head.next
self.head.prev = None # type: ignore
popped.next = None # type: ignore
popped.prev = None # type: ignore
return popped
raise IndexError("The Doubly Linked List is Empty")
def pop_tail(self):
if self.tail:
popped = self.tail
if self.tail == self.head:
self.head = None # type: ignore
self.tail = None # type: ignore
else:
self.tail = self.tail.prev
self.tail.next = None # type: ignore
popped.next = None # type: ignore
popped.prev = None # type: ignore
return popped
raise IndexError("The Doubly Linked List is Empty")
def __str__(self) -> str:
if self.head is None:
return "DoublyLinkedList([])"
return f"DoublyLinkedList([ {self.head} ])"
def __repr__(self) -> str:
return self.__str__()
if __name__ == "__main__":
linked = DoublyLinkedList(Node(5)) # [5]
linked.push_head(Node(4)) # [(4) <-> 5]
linked.push_head(Node(3)) # [(3) <-> 4 <-> 5]
linked.push_head(Node(2)) # [(2) <-> 3 <-> 4 <-> 5]
linked.push_tail(Node(6)) # [2 <-> 3 <-> 4 <-> 5 <-> (6)]
linked.push_tail(Node(7)) # [2 <-> 3 <-> 4 <-> 5 <-> 6 <-> (7)]
print("Linked List:", linked)
print(f"Popped Head: {linked.pop_head()}") # Node(2) is popped out
print(f"Popped Head: {linked.pop_head()}") # Node(3) is popped out
print("Linked List:", linked)
print(f"Popped Tail: {linked.pop_tail()}") # Node(7) is popped out
print(f"Popped Tail: {linked.pop_tail()}") # Node(6) is popped out
print("Linked List:", linked) # [ 4 <-> 5 ]