-
Notifications
You must be signed in to change notification settings - Fork 1
/
Doubly Linked List.py
218 lines (195 loc) · 7 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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
class Node:
"""Class to represent a node in Python3"""
def __init__(self, data):
self.data = data # Node value
self.next = None # Next node
self.prev = None # Previus node
class DoublyLinkedList:
"""Class to represent a doubly linked list in Python3"""
def __init__(self):
self._first = None # First element of list
self._last = None # Last element of list
self._size = 0 # The size of list
def getItemByIndex(self, index):
"""Auxiliary method that returns the node by the index"""
if index < 0:
index = self._size + index
pointer = self._first
for _ in range(index):
if pointer.next:
pointer = pointer.next
else:
raise IndexError("Index out of range")
return pointer
def processIndex(self, index):
"""Auxiliary method that helps with negative indexs"""
if index is None:
index = self._size - 1
elif index == self._size or abs(index) > self._size:
raise IndexError("Index out of range")
if index < 0:
index = self._size + index
return index
def append(self, elem):
"""Appends a new element in the end of list"""
node = Node(elem)
if self._first: # if is not None
self._last.next = node
node.prev = self._last
node.next = None
self._last = node
else:
self._first = self._last = node
self._size += 1
def remove(self, elem):
"""Removes the first occurrence of the element from the list"""
if self._size == 0:
raise Exception("Empty list")
index = self.index(elem)
del self[index]
def empty(self):
"""Returns true if the stack is empty, otherwise, it returns false"""
if self._size == 0:
return True
return False
def insert(self, index, elem):
"""Inserts a new element by index"""
node = Node(elem)
if index < 0 and abs(index) > self._size:
index = 0
elif index < 0:
index = self._size + index
if self._size == 0 or index >= self._size:
self.append(elem)
elif index == 0:
node.next = self._first
self._first.prev = node
self._first = node
self._size += 1
elif index > 0:
node_next = self.getItemByIndex(index)
node_prev = self.getItemByIndex(index - 1)
node.next = node_next
node.prev = node_prev
node_next.prev = node
node_prev.next = node
self._size += 1
else:
raise IndexError("Index out of range")
def pop(self, index=None):
"""Removes and returns the last element from the list"""
if self._size == 0:
raise Exception("Empty list")
index = self.processIndex(index)
if self._size == 1:
elem = self._last.data
self.clear()
else:
elem = self.getItemByIndex(index).data
del self[index]
return elem
def clear(self):
"""Restores the list to its starting point (Empty)"""
self._first = None
self._last = None
self._size = 0
def count(self, elem):
"""Returns the number of elements with the specified value"""
pointer = self._first
cont = 0
while pointer != None:
if pointer.data == elem:
cont += 1
pointer = pointer.next
return cont
def index(self, elem):
"""Returns the index of specified element"""
pointer = self._first
cont = 0
while pointer:
if pointer.data == elem:
return cont
else:
pointer = pointer.next
cont += 1
raise ValueError(f"{elem} not in list")
def reverse(self):
"""Reverses the original list"""
if self._size == 0:
raise IndexError("Empty list")
pointer = self._first
while pointer:
pointer.next, pointer.prev = pointer.prev, pointer.next
pointer = pointer.prev
self._first, self._last = self._last, self._first
def createReversed(self):
"""Creates and returns a reversed new list"""
if self._size == 0:
raise IndexError("Empty list")
new = DoublyLinkedList()
pointer = self._last
while pointer:
new.append(pointer.data)
pointer = pointer.prev
return new
def __len__(self):
"""Returns the size of list; Ex: len(obj)"""
return self._size
def __getitem__(self, index):
"""Returns an element that corresponding to the index; Ex: obj[index]"""
if self._size == 0:
raise IndexError("Empty list")
index = self.processIndex(index)
pointer = self.getItemByIndex(index)
return pointer.data
def __setitem__(self, index, elem):
"""Sets the value by the index; Ex: obj[index] = value"""
if self._size == 0:
raise IndexError("Empty list")
index = self.processIndex(index)
pointer = self.getItemByIndex(index)
pointer.data = elem
def __delitem__(self, index):
"""Removes an element that corresponding to the index; Ex: obj[index]"""
if self._size == 0:
raise IndexError("Empty list")
index = self.processIndex(index)
if index == 0:
self._first = self._first.next
self._first.prev = None
elif index == self._size - 1:
self._last = self._last.prev
self._last.next = None
else:
node_next = self.getItemByIndex(index + 1)
node_prev = self.getItemByIndex(index - 1)
node_next.prev = node_prev
node_prev.next = node_next
self._size -= 1
def __del__(self):
"""Destructor method"""
def __str__(self):
"""Method to represent a doubly linked list (user)"""
if self._size == 0:
return "\033[1;34mNone\033[0;0m" + " <-> " + "\033[1;34mNone\033[0;0m"
rep = "\033[1;34mNone\033[0;0m" + " <- {} " + "\033[1;34mNone\033[0;0m"
pointer = self._first
aux = ""
while pointer != None:
if pointer == self._first and pointer.next is None:
aux += "\033[1;31m" + str(pointer.data) + "\033[0;0m" + " -> "
break
elif pointer.next is None:
aux += f"{pointer.data} -> "
break
else:
if self._first == pointer:
aux += "\033[1;31m" + str(pointer.data) + "\033[0;0m" + " <-> "
else:
aux += f"{pointer.data} <-> "
pointer = pointer.next
rep = rep.format(aux)
return rep
def __repr__(self):
"""Method to represent a doubly linked list (developer)"""
return str(self)