diff --git a/python/06_linkedlist/singly_linked_list.py b/python/06_linkedlist/singly_linked_list.py new file mode 100644 index 00000000..f5565f39 --- /dev/null +++ b/python/06_linkedlist/singly_linked_list.py @@ -0,0 +1,139 @@ +""" + 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) \ No newline at end of file