-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlinked_list.py
145 lines (126 loc) · 4.07 KB
/
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
137
138
139
140
141
142
143
144
145
from dataclasses import dataclass
from typing import Optional
@dataclass
class SingleLinkedNode:
value: int
next: Optional['SingleLinkedNode'] = None
@dataclass
class DoubleLinkedNode:
value: int
next: Optional['DoubleLinkedNode'] = None
prev: Optional['DoubleLinkedNode'] = None
class SingleLinkedList:
def __init__(self):
self.head = None
self.tail = None
self.size = 0
def __repr__(self):
return f'head {self.head} tail {self.tail}'
def find(self, value: int):
current = self.head
index = 0
while current.next:
if current.value == value:
return index
current = current.next
index += 1
return -1 if not current.value == value else index
def index(self, index: int):
if index < 0 or index > self.size-1:
raise IndexError()
current = self.head
for _ in range(index):
current = current.next
return current
def add(self, new_node, index):
if index == 0:
new_node.next = self.head
self.head = new_node
else:
previous_elem = self.index(index-1)
new_node.next = previous_elem.next
previous_elem.next = new_node
self.size += 1
def remove(self, index):
if index == 0:
self.head = self.head.next
else:
previous_elem = self.index(index-1)
previous_elem.next = previous_elem.next.next
self.size -= 1
def display(self):
current = self.head
out = [current.value]
while current.next:
out.append(current.next.value)
current = current.next
return out
class DoubleLinkedList(SingleLinkedList):
def add(self, new_node, index):
if not self.head:
self.head = new_node
self.size += 1
return
if not self.tail:
self.tail = new_node
self.head.next = self.tail
self.size += 1
return
if index == 0:
new_node.next = self.head
self.head.prev = new_node
self.head = new_node
elif index == self.size:
new_node.prev = self.tail
self.tail.next = new_node
self.tail = new_node
else:
previous_elem = self.index(index-1)
new_node.next = previous_elem.next
new_node.prev = previous_elem
previous_elem.next = new_node
new_node.next.prev = new_node
self.size += 1
def remove(self, index):
if index == 0:
self.head = self.head.next
self.head.prev = None
elif index == self.size - 1:
self.tail = self.tail.prev
self.tail.next = None
else:
previous_elem = self.index(index-1)
previous_elem.next = previous_elem.next.next
previous_elem.next.prev = previous_elem
self.size -= 1
lst1 = SingleLinkedList()
lst1.head = SingleLinkedNode(1, next=SingleLinkedNode(2, next=SingleLinkedNode(3)))
lst1.tail = SingleLinkedNode(3)
lst1.size = 3
assert lst1.index(1) == SingleLinkedNode(2, next=SingleLinkedNode(3))
assert lst1.find(2)
assert lst1.find(1) == 0
assert lst1.find(4) == -1
another_lst = SingleLinkedList()
another_lst.add(SingleLinkedNode(1), index=0)
assert another_lst.display() == [1]
another_lst.add(SingleLinkedNode(2), index=1)
assert another_lst.display() == [1, 2]
another_lst.add(SingleLinkedNode(1), index=2)
assert another_lst.display() == [1, 2, 1]
another_lst.add(SingleLinkedNode(6), index=1)
assert another_lst.display() == [1, 6, 2, 1]
another_lst.remove(2)
assert another_lst.display() == [1, 6, 1]
lst2 = DoubleLinkedList()
lst2.add(DoubleLinkedNode(1), index=0)
assert lst2.display() == [1]
lst2.add(DoubleLinkedNode(2), index=1)
assert lst2.display() == [1, 2]
lst2.add(DoubleLinkedNode(3), index=1)
assert lst2.display() == [1, 3, 2]
assert lst2.find(3) == 1
assert lst2.find(1) == 0
assert lst2.find(2) == 2
lst2.remove(1)
assert lst2.display() == [1, 2]