139 lines
3.9 KiB
Python
139 lines
3.9 KiB
Python
"""
|
|
1) Insertion, deletion and search of singly-linked list;
|
|
2) Assumes int type for data in list nodes.
|
|
|
|
Author: Wenru
|
|
"""
|
|
from typing import Optional
|
|
|
|
class Node:
|
|
|
|
def __init__(self, data: int, next=None):
|
|
self.data = data
|
|
self._next = next
|
|
|
|
|
|
class SinglyLinkedList:
|
|
|
|
def __init__(self):
|
|
self._head = None
|
|
|
|
def find_by_value(self, value: int) -> Optional[Node]:
|
|
p = self._head
|
|
while p and p.data != value:
|
|
p = p._next
|
|
|
|
return p
|
|
|
|
def find_by_index(self, index: int) -> Optional[Node]:
|
|
p = self._head
|
|
position = 0
|
|
while p and position != index:
|
|
p = p._next
|
|
position += 1
|
|
|
|
return p
|
|
|
|
def insert_value_to_head(self, value: int):
|
|
new_node = Node(value)
|
|
self.insert_node_to_head(new_node)
|
|
|
|
def insert_node_to_head(self, new_node: Node):
|
|
if new_node:
|
|
new_node._next = self._head
|
|
self._head = new_node
|
|
|
|
def insert_value_after(self, node: Node, value: int):
|
|
new_node = Node(value)
|
|
self.insert_node_after(node, new_node)
|
|
|
|
def insert_node_after(self, node: Node, new_node: Node):
|
|
if not node or not new_node:
|
|
return
|
|
new_node._next = node._next
|
|
node._next = new_node
|
|
|
|
def insert_value_before(self, node: Node, value: int):
|
|
new_node = Node(value)
|
|
self.insert_node_before(node, new_node)
|
|
|
|
def insert_node_before(self, node: Node, new_node: Node):
|
|
if not self._head or not node or not new_node:
|
|
return
|
|
if self._head == node:
|
|
self.insert_node_to_head(new_node)
|
|
return
|
|
current = self._head
|
|
while current._next and current._next != node:
|
|
current = current._next
|
|
if not current._next: # node is not even in the list
|
|
return
|
|
new_node._next = node
|
|
current._next = new_node
|
|
|
|
def delete_by_node(self, node: Node):
|
|
if not self._head or not node:
|
|
return
|
|
if node._next:
|
|
node.data = node._next.data
|
|
node._next = node._next._next
|
|
return
|
|
# node is the last one or not in the list
|
|
current = self._head
|
|
while current and current._next != node:
|
|
current = current._next
|
|
if not current: # node not in the list
|
|
return
|
|
current._next = None
|
|
|
|
def delete_by_value(self, value: int):
|
|
if not self._head or not value:
|
|
return
|
|
fake_head = Node(value+1)
|
|
fake_head._next = self._head
|
|
prev, current = fake_head, self._head
|
|
while current:
|
|
if current.data != value:
|
|
prev._next = current
|
|
prev = prev._next
|
|
current = current._next
|
|
if prev._next:
|
|
prev._next = None
|
|
self._head = fake_head._next # in case head.data == value
|
|
|
|
def __repr__(self) -> str:
|
|
nums = []
|
|
current = self._head
|
|
while current:
|
|
nums.append(current.data)
|
|
current = current._next
|
|
if len(nums) > 0:
|
|
return "->".join(str(num) for num in nums)
|
|
else:
|
|
return ""
|
|
|
|
def print_all(self):
|
|
current = self._head
|
|
if current:
|
|
print(f"{current.data}", end="")
|
|
current = current._next
|
|
while current:
|
|
print(f"->{current.data}", end="")
|
|
current = current._next
|
|
print("\n", flush=True)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
l = SinglyLinkedList()
|
|
for i in range(15):
|
|
l.insert_value_to_head(i)
|
|
node9 = l.find_by_value(9)
|
|
l.insert_value_before(node9, 20)
|
|
l.insert_value_before(node9, 16)
|
|
l.insert_value_before(node9, 16)
|
|
l.delete_by_value(16)
|
|
node11 = l.find_by_index(3)
|
|
l.delete_by_node(node11)
|
|
l.delete_by_node(l._head)
|
|
l.delete_by_value(13)
|
|
print(l) |