dsa.singlylinkedlist
Module containing singly linked list class.
1""" Module containing singly linked list class. """ 2 3class Node: 4 """ 5 A singly linked list node implementation. 6 """ 7 def __init__(self, value): 8 """ 9 A singly linked list node. 10 Args: 11 value: The value of the node. 12 """ 13 #: value of the node 14 self.value = value 15 #: reference to the next node 16 self.next = None 17 18class LinkedList: 19 """ 20 A singly linked list implementation. 21 """ 22 def __init__(self, head: Node=None, tail: Node=None, count: int=0): 23 """ 24 Initialize a singly linked list. 25 26 if only the head node is specified, tail is set to the head node and count is automatically set to 0 27 if both head and tail nodes are specified, count should be specified as well 28 29 Args: 30 head: The reference to the head node. 31 tail: The reference to the tail node. 32 count: The number of nodes in the linked list. 33 34 """ 35 self.head = head 36 if head and tail is None: 37 self.tail = head 38 self.count = 1 39 else: 40 self.tail = tail 41 self.count = count 42 43 @classmethod 44 def from_list(cls, mylist=None): 45 """ 46 Create a linked list from a list. 47 48 Args: 49 mylist: A list or container to convert from. 50 51 Returns: 52 A linked list containing the items from mylist. 53 """ 54 ll = cls() 55 for value in mylist: 56 ll.append(value) 57 58 return ll 59 60 def to_list(self) -> list: 61 """ 62 Create a list with contents of the linked list. 63 64 Returns: 65 List with contents of linked list. 66 """ 67 mylist = [] 68 current = self.head 69 while current: 70 mylist.append(current.value) 71 current = current.next 72 return mylist 73 74 def print(self): 75 """ 76 Print the contents of the linked list. 77 """ 78 current = self.head 79 while current: 80 print(current.value, end=" ") 81 current = current.next 82 print() 83 84 85 def __repr__(self): 86 """ 87 Return a string representation of the linked list. 88 89 Returns: 90 A string representation of the linked list. 91 """ 92 s = "" 93 current = self.head 94 while current: 95 s += str(current.value) + " " 96 current = current.next 97 98 return f"[ {s}] Count: {self.count}" 99 100 def __getitem__(self, index: int) -> Node: 101 """ 102 Return value at a specified index. Raise IndexError if index is out of bounds. 103 104 Args: 105 index: Index of value. 106 107 Raises: 108 IndexError: If index is out of bounds. 109 110 Returns: 111 The value at the specified index. 112 """ 113 i = 0 114 current = self.head 115 while current: 116 if i == index: 117 return current.value 118 current = current.next 119 i += 1 120 raise IndexError("Index Out of Bounds") 121 122 def __len__(self) -> int: 123 """ 124 Return the number of elements in the linked list. 125 """ 126 return self.count 127 128 def is_empty(self) -> bool: 129 """ 130 Check if the linked list is empty. 131 """ 132 return self.count == 0 133 134 def search(self, value) -> int: 135 """ 136 Search for a value in the linked list. 137 138 Args: 139 value: The value to search for. 140 141 Returns: 142 Return index of found value. 143 144 Raises: 145 Exception: If value is not found. 146 """ 147 i = 0 148 current = self.head 149 while current: 150 if current.value == value: 151 return i 152 i += 1 153 current = current.next 154 raise Exception("Value not found") 155 156 def insert(self, index: int, value): 157 """ 158 Insert a value at a specified index. Raise exception if index is out of bounds. 159 160 Args: 161 index (int): The index to insert a value. 162 value: The value to append. 163 164 Returns: 165 None 166 167 Raises: 168 IndexError: If index is out of bounds. 169 """ 170 i = 0 171 172 # insert front 173 if index == 0: 174 self.prepend(value) 175 return 176 elif index == self.count: # insert at end 177 self.append(value) 178 return 179 elif index > self.count: 180 raise IndexError("Index Out of Bounds") 181 182 # find node to insert after 183 current = self.head 184 while index < i or current: 185 i += 1 186 if i == index: 187 break 188 current = current.next 189 190 if index > i: 191 raise IndexError("Index Out of Bounds") 192 193 new_node = Node(value) 194 tmp = current.next 195 current.next = new_node 196 new_node.next = tmp 197 self.count += 1 198 199 def prepend(self, value): 200 """ 201 Place a value at the beginning of the linked list. 202 203 Args: 204 value: A value to append. 205 206 Returns: 207 None 208 """ 209 new_node = Node(value) 210 new_node.next = self.head 211 self.head = new_node 212 self.count += 1 213 214 def append(self, value): 215 """ 216 Place a value at the end of the linked list. 217 218 Args: 219 value: A value to append. 220 221 Returns: 222 None 223 224 Raises: 225 IndexError: If linked list is empty or index is not found. 226 """ 227 if self.head is None: 228 self.head = Node(value) 229 if self.count == 0: 230 self.tail = self.head 231 self.count += 1 232 return 233 234 # go to the end of the list 235 new_node = Node(value) 236 self.tail.next = new_node 237 self.tail = new_node 238 239 self.count += 1 240 241 def delete(self, index: int): 242 """ 243 Delete a node at a specified index. Raise IndexError if linked list is empty or if index is not found. 244 245 Args: 246 index: Index of element to be deleted. 247 248 Returns: 249 None 250 251 Raises: 252 IndexError: If linked list is empty or index is not found. 253 """ 254 if index == 0: 255 self.delete_head() 256 return 257 elif index + 1 == self.count: 258 self.delete_tail() 259 return 260 261 i = 0 262 current = self.head 263 prev = None 264 while current: 265 if index == i: 266 if prev is not None: 267 prev.next = current.next 268 else: 269 self.head = current.next 270 self.count -= 1 271 return 272 i += 1 273 prev = current 274 current = current.next 275 raise IndexError("Index not found") 276 277 def delete_head(self): 278 """ 279 Delete the head node in the linked list. Raise IndexError if linked list is empty. 280 281 Returns: 282 None 283 284 Raises: 285 IndexError: If linked list is empty. 286 """ 287 if self.head is None: 288 raise IndexError("LinkedList is Empty") 289 self.head = self.head.next 290 self.count -= 1 291 292 def delete_tail(self): 293 """ 294 Delete the last node in the linked list. Raise IndexError if linked list is empty. 295 296 Returns: 297 None 298 299 Raises: 300 IndexError: If linked list is empty. 301 """ 302 if self.head is None: 303 raise IndexError("LinkedList is Empty") 304 305 if self.head.next is None: 306 self.head = None 307 self.count -= 1 308 return 309 310 current = self.head 311 while current.next.next: 312 current = current.next 313 314 current.next = None 315 self.tail = current 316 self.count -= 1 317 318if __name__ == "__main__": 319 ll = LinkedList.from_list(range(10)) 320 ll = LinkedList() 321 322 for _ in range(15): 323 ll.append(_) 324 assert (ll.head.value == 0) 325 assert (ll.tail.value == 14) 326 assert (ll.count == 15) 327 328 print(ll.to_list()) 329 ll.insert(1, -1) 330 print(ll.to_list()) 331 assert (ll[1] == -1) 332# self.assertEqual(ll.count, 16) 333 ll.insert(0, -2) 334# ll.prepend(-2) 335 print(ll.to_list()) 336 assert (ll[0] == -2)
4class Node: 5 """ 6 A singly linked list node implementation. 7 """ 8 def __init__(self, value): 9 """ 10 A singly linked list node. 11 Args: 12 value: The value of the node. 13 """ 14 #: value of the node 15 self.value = value 16 #: reference to the next node 17 self.next = None
A singly linked list node implementation.
19class LinkedList: 20 """ 21 A singly linked list implementation. 22 """ 23 def __init__(self, head: Node=None, tail: Node=None, count: int=0): 24 """ 25 Initialize a singly linked list. 26 27 if only the head node is specified, tail is set to the head node and count is automatically set to 0 28 if both head and tail nodes are specified, count should be specified as well 29 30 Args: 31 head: The reference to the head node. 32 tail: The reference to the tail node. 33 count: The number of nodes in the linked list. 34 35 """ 36 self.head = head 37 if head and tail is None: 38 self.tail = head 39 self.count = 1 40 else: 41 self.tail = tail 42 self.count = count 43 44 @classmethod 45 def from_list(cls, mylist=None): 46 """ 47 Create a linked list from a list. 48 49 Args: 50 mylist: A list or container to convert from. 51 52 Returns: 53 A linked list containing the items from mylist. 54 """ 55 ll = cls() 56 for value in mylist: 57 ll.append(value) 58 59 return ll 60 61 def to_list(self) -> list: 62 """ 63 Create a list with contents of the linked list. 64 65 Returns: 66 List with contents of linked list. 67 """ 68 mylist = [] 69 current = self.head 70 while current: 71 mylist.append(current.value) 72 current = current.next 73 return mylist 74 75 def print(self): 76 """ 77 Print the contents of the linked list. 78 """ 79 current = self.head 80 while current: 81 print(current.value, end=" ") 82 current = current.next 83 print() 84 85 86 def __repr__(self): 87 """ 88 Return a string representation of the linked list. 89 90 Returns: 91 A string representation of the linked list. 92 """ 93 s = "" 94 current = self.head 95 while current: 96 s += str(current.value) + " " 97 current = current.next 98 99 return f"[ {s}] Count: {self.count}" 100 101 def __getitem__(self, index: int) -> Node: 102 """ 103 Return value at a specified index. Raise IndexError if index is out of bounds. 104 105 Args: 106 index: Index of value. 107 108 Raises: 109 IndexError: If index is out of bounds. 110 111 Returns: 112 The value at the specified index. 113 """ 114 i = 0 115 current = self.head 116 while current: 117 if i == index: 118 return current.value 119 current = current.next 120 i += 1 121 raise IndexError("Index Out of Bounds") 122 123 def __len__(self) -> int: 124 """ 125 Return the number of elements in the linked list. 126 """ 127 return self.count 128 129 def is_empty(self) -> bool: 130 """ 131 Check if the linked list is empty. 132 """ 133 return self.count == 0 134 135 def search(self, value) -> int: 136 """ 137 Search for a value in the linked list. 138 139 Args: 140 value: The value to search for. 141 142 Returns: 143 Return index of found value. 144 145 Raises: 146 Exception: If value is not found. 147 """ 148 i = 0 149 current = self.head 150 while current: 151 if current.value == value: 152 return i 153 i += 1 154 current = current.next 155 raise Exception("Value not found") 156 157 def insert(self, index: int, value): 158 """ 159 Insert a value at a specified index. Raise exception if index is out of bounds. 160 161 Args: 162 index (int): The index to insert a value. 163 value: The value to append. 164 165 Returns: 166 None 167 168 Raises: 169 IndexError: If index is out of bounds. 170 """ 171 i = 0 172 173 # insert front 174 if index == 0: 175 self.prepend(value) 176 return 177 elif index == self.count: # insert at end 178 self.append(value) 179 return 180 elif index > self.count: 181 raise IndexError("Index Out of Bounds") 182 183 # find node to insert after 184 current = self.head 185 while index < i or current: 186 i += 1 187 if i == index: 188 break 189 current = current.next 190 191 if index > i: 192 raise IndexError("Index Out of Bounds") 193 194 new_node = Node(value) 195 tmp = current.next 196 current.next = new_node 197 new_node.next = tmp 198 self.count += 1 199 200 def prepend(self, value): 201 """ 202 Place a value at the beginning of the linked list. 203 204 Args: 205 value: A value to append. 206 207 Returns: 208 None 209 """ 210 new_node = Node(value) 211 new_node.next = self.head 212 self.head = new_node 213 self.count += 1 214 215 def append(self, value): 216 """ 217 Place a value at the end of the linked list. 218 219 Args: 220 value: A value to append. 221 222 Returns: 223 None 224 225 Raises: 226 IndexError: If linked list is empty or index is not found. 227 """ 228 if self.head is None: 229 self.head = Node(value) 230 if self.count == 0: 231 self.tail = self.head 232 self.count += 1 233 return 234 235 # go to the end of the list 236 new_node = Node(value) 237 self.tail.next = new_node 238 self.tail = new_node 239 240 self.count += 1 241 242 def delete(self, index: int): 243 """ 244 Delete a node at a specified index. Raise IndexError if linked list is empty or if index is not found. 245 246 Args: 247 index: Index of element to be deleted. 248 249 Returns: 250 None 251 252 Raises: 253 IndexError: If linked list is empty or index is not found. 254 """ 255 if index == 0: 256 self.delete_head() 257 return 258 elif index + 1 == self.count: 259 self.delete_tail() 260 return 261 262 i = 0 263 current = self.head 264 prev = None 265 while current: 266 if index == i: 267 if prev is not None: 268 prev.next = current.next 269 else: 270 self.head = current.next 271 self.count -= 1 272 return 273 i += 1 274 prev = current 275 current = current.next 276 raise IndexError("Index not found") 277 278 def delete_head(self): 279 """ 280 Delete the head node in the linked list. Raise IndexError if linked list is empty. 281 282 Returns: 283 None 284 285 Raises: 286 IndexError: If linked list is empty. 287 """ 288 if self.head is None: 289 raise IndexError("LinkedList is Empty") 290 self.head = self.head.next 291 self.count -= 1 292 293 def delete_tail(self): 294 """ 295 Delete the last node in the linked list. Raise IndexError if linked list is empty. 296 297 Returns: 298 None 299 300 Raises: 301 IndexError: If linked list is empty. 302 """ 303 if self.head is None: 304 raise IndexError("LinkedList is Empty") 305 306 if self.head.next is None: 307 self.head = None 308 self.count -= 1 309 return 310 311 current = self.head 312 while current.next.next: 313 current = current.next 314 315 current.next = None 316 self.tail = current 317 self.count -= 1
A singly linked list implementation.
23 def __init__(self, head: Node=None, tail: Node=None, count: int=0): 24 """ 25 Initialize a singly linked list. 26 27 if only the head node is specified, tail is set to the head node and count is automatically set to 0 28 if both head and tail nodes are specified, count should be specified as well 29 30 Args: 31 head: The reference to the head node. 32 tail: The reference to the tail node. 33 count: The number of nodes in the linked list. 34 35 """ 36 self.head = head 37 if head and tail is None: 38 self.tail = head 39 self.count = 1 40 else: 41 self.tail = tail 42 self.count = count
Initialize a singly linked list.
if only the head node is specified, tail is set to the head node and count is automatically set to 0 if both head and tail nodes are specified, count should be specified as well
Args: head: The reference to the head node. tail: The reference to the tail node. count: The number of nodes in the linked list.
44 @classmethod 45 def from_list(cls, mylist=None): 46 """ 47 Create a linked list from a list. 48 49 Args: 50 mylist: A list or container to convert from. 51 52 Returns: 53 A linked list containing the items from mylist. 54 """ 55 ll = cls() 56 for value in mylist: 57 ll.append(value) 58 59 return ll
Create a linked list from a list.
Args: mylist: A list or container to convert from.
Returns: A linked list containing the items from mylist.
61 def to_list(self) -> list: 62 """ 63 Create a list with contents of the linked list. 64 65 Returns: 66 List with contents of linked list. 67 """ 68 mylist = [] 69 current = self.head 70 while current: 71 mylist.append(current.value) 72 current = current.next 73 return mylist
Create a list with contents of the linked list.
Returns: List with contents of linked list.
75 def print(self): 76 """ 77 Print the contents of the linked list. 78 """ 79 current = self.head 80 while current: 81 print(current.value, end=" ") 82 current = current.next 83 print()
Print the contents of the linked list.
129 def is_empty(self) -> bool: 130 """ 131 Check if the linked list is empty. 132 """ 133 return self.count == 0
Check if the linked list is empty.
135 def search(self, value) -> int: 136 """ 137 Search for a value in the linked list. 138 139 Args: 140 value: The value to search for. 141 142 Returns: 143 Return index of found value. 144 145 Raises: 146 Exception: If value is not found. 147 """ 148 i = 0 149 current = self.head 150 while current: 151 if current.value == value: 152 return i 153 i += 1 154 current = current.next 155 raise Exception("Value not found")
Search for a value in the linked list.
Args: value: The value to search for.
Returns: Return index of found value.
Raises: Exception: If value is not found.
157 def insert(self, index: int, value): 158 """ 159 Insert a value at a specified index. Raise exception if index is out of bounds. 160 161 Args: 162 index (int): The index to insert a value. 163 value: The value to append. 164 165 Returns: 166 None 167 168 Raises: 169 IndexError: If index is out of bounds. 170 """ 171 i = 0 172 173 # insert front 174 if index == 0: 175 self.prepend(value) 176 return 177 elif index == self.count: # insert at end 178 self.append(value) 179 return 180 elif index > self.count: 181 raise IndexError("Index Out of Bounds") 182 183 # find node to insert after 184 current = self.head 185 while index < i or current: 186 i += 1 187 if i == index: 188 break 189 current = current.next 190 191 if index > i: 192 raise IndexError("Index Out of Bounds") 193 194 new_node = Node(value) 195 tmp = current.next 196 current.next = new_node 197 new_node.next = tmp 198 self.count += 1
Insert a value at a specified index. Raise exception if index is out of bounds.
Args: index (int): The index to insert a value. value: The value to append.
Returns: None
Raises: IndexError: If index is out of bounds.
200 def prepend(self, value): 201 """ 202 Place a value at the beginning of the linked list. 203 204 Args: 205 value: A value to append. 206 207 Returns: 208 None 209 """ 210 new_node = Node(value) 211 new_node.next = self.head 212 self.head = new_node 213 self.count += 1
Place a value at the beginning of the linked list.
Args: value: A value to append.
Returns: None
215 def append(self, value): 216 """ 217 Place a value at the end of the linked list. 218 219 Args: 220 value: A value to append. 221 222 Returns: 223 None 224 225 Raises: 226 IndexError: If linked list is empty or index is not found. 227 """ 228 if self.head is None: 229 self.head = Node(value) 230 if self.count == 0: 231 self.tail = self.head 232 self.count += 1 233 return 234 235 # go to the end of the list 236 new_node = Node(value) 237 self.tail.next = new_node 238 self.tail = new_node 239 240 self.count += 1
Place a value at the end of the linked list.
Args: value: A value to append.
Returns: None
Raises: IndexError: If linked list is empty or index is not found.
242 def delete(self, index: int): 243 """ 244 Delete a node at a specified index. Raise IndexError if linked list is empty or if index is not found. 245 246 Args: 247 index: Index of element to be deleted. 248 249 Returns: 250 None 251 252 Raises: 253 IndexError: If linked list is empty or index is not found. 254 """ 255 if index == 0: 256 self.delete_head() 257 return 258 elif index + 1 == self.count: 259 self.delete_tail() 260 return 261 262 i = 0 263 current = self.head 264 prev = None 265 while current: 266 if index == i: 267 if prev is not None: 268 prev.next = current.next 269 else: 270 self.head = current.next 271 self.count -= 1 272 return 273 i += 1 274 prev = current 275 current = current.next 276 raise IndexError("Index not found")
Delete a node at a specified index. Raise IndexError if linked list is empty or if index is not found.
Args: index: Index of element to be deleted.
Returns: None
Raises: IndexError: If linked list is empty or index is not found.
278 def delete_head(self): 279 """ 280 Delete the head node in the linked list. Raise IndexError if linked list is empty. 281 282 Returns: 283 None 284 285 Raises: 286 IndexError: If linked list is empty. 287 """ 288 if self.head is None: 289 raise IndexError("LinkedList is Empty") 290 self.head = self.head.next 291 self.count -= 1
Delete the head node in the linked list. Raise IndexError if linked list is empty.
Returns: None
Raises: IndexError: If linked list is empty.
293 def delete_tail(self): 294 """ 295 Delete the last node in the linked list. Raise IndexError if linked list is empty. 296 297 Returns: 298 None 299 300 Raises: 301 IndexError: If linked list is empty. 302 """ 303 if self.head is None: 304 raise IndexError("LinkedList is Empty") 305 306 if self.head.next is None: 307 self.head = None 308 self.count -= 1 309 return 310 311 current = self.head 312 while current.next.next: 313 current = current.next 314 315 current.next = None 316 self.tail = current 317 self.count -= 1
Delete the last node in the linked list. Raise IndexError if linked list is empty.
Returns: None
Raises: IndexError: If linked list is empty.