dsa.tree API documentation

# dsa.tree

Module containing tree class.

View Source

      1""" Module containing tree class. """
      2
      3class TreeNode:
      4    """
      5    A binary tree node implementation.
      6    """
      7    def __init__(self, value, left=None, right=None):
      8        """
      9        TreeNode constructor.
     10
     11        Args:
     12            value: The value of the node.
     13            left: Reference to the left node.
     14            right: Reference to the right node.
     15        """
     16        self.value = value
     17        self.left = left
     18        self.right = right
     19
     20    def copy(self):
     21        """
     22        Return a copy of the node.
     23        """
     24        new_node = TreeNode(self.value)
     25        if self.left:
     26            new_node.left = self.left.copy()
     27        if self.right:
     28            new_node.right = self.right.copy()
     29        return new_node
     30
     31    def print(self, level=0):
     32        """
     33        Print the contents of a node.
     34
     35        Args:
     36            level: starting level of node
     37        """
     38        if self.right:
     39            self.right.print(level + 1)
     40        print("   " * level + str(self.value))
     41        if self.left:
     42            self.left.print(level + 1)
     43
     44    def __lt__(self, other):
     45        """
     46        Compare the value of two nodes.
     47        """
     48        return self.value < other.value
     49
     50    def __repr__(self):
     51        """
     52        Return the string representation of a node.
     53        """
     54        if self.value is None:
     55            return "none"
     56        else:
     57            return str(self.value)
     58
     59class Tree:
     60    """
     61    A binary search tree (BST) implementation. Can be treated as a plain binary tree if operations (insert, search, delete) are not used and nodes are set manually.
     62    """
     63    def __init__(self, root=None):
     64        """
     65        Args:
     66            root: Root node of the Tree.
     67        """
     68        self.root = root
     69
     70    def search(self, value):
     71        """
     72        Search for a value in the binary search tree.
     73
     74        Args:
     75            value: Value to search for.
     76
     77        Returns:
     78            node with matching value
     79
     80        Raises:
     81            ValueError: if value is not found
     82        """
     83        current = self.root
     84
     85        while current is not None:
     86            if value == current.value:
     87                return current
     88            elif value < current.value:
     89                current = current.left
     90            elif value > current.value:
     91                current = current.right
     92
     93        raise ValueError(f"Value {value} not found in the tree")
     94
     95    def insert(self, value):
     96        """
     97        Insert a value in the binary search tree.
     98
     99        Args:
    100            value: The value to insert.
    101
    102        Returns:
    103            The root of the tree after deletion.
    104
    105        Raises:
    106            ValueError: if value is already in the tree
    107        """
    108        self.root = self.insert_rec(self.root, value)
    109        return self.root
    110
    111    def insert_rec(self, root, value):
    112        if root is None:
    113            return TreeNode(value)
    114        if value < root.value:
    115            root.left = self.insert_rec(root.left, value)
    116        elif value > root.value:
    117            root.right = self.insert_rec(root.right, value)
    118        else:
    119            raise ValueError("Value already exists in the tree")
    120        return root
    121
    122    def insert_iterative(self, value):
    123        """
    124        Insert a value in the binary search tree (iterative implementation).
    125
    126        Args:
    127            value: The value to insert.
    128
    129        Returns:
    130            None
    131
    132        Raises:
    133            ValueError: if value is already in the tree
    134        """
    135        current = self.root
    136        if self.root is None:
    137            self.root = TreeNode(value)
    138            return
    139
    140        while current is not None:
    141            if value < current.value:
    142                if current.left is None:
    143                    current.left = TreeNode(value)
    144                    return
    145                else:
    146                    current = current.left
    147            elif value > current.value:
    148                if current.right is None:
    149                    current.right = TreeNode(value)
    150                    return
    151                else:
    152                    current = current.right
    153            else:
    154                return
    155
    156    def delete(self, value):
    157        """
    158        Delete a value from the binary search tree.
    159
    160        Args:
    161            value: The value to delete.
    162
    163        Returns:
    164            The root of the tree after insertion.
    165
    166
    167        Raises:
    168            ValueError: if value is not found.
    169        """
    170        self.root = self.delete_node(self.root, value)
    171        return self.root
    172
    173    def delete_node(self, node, value):
    174        """
    175        Helper function to delete a value from the binary search tree. (Use delete() instead)
    176
    177        Args:
    178            value: The value to delete.
    179            node: The current node.
    180
    181        Returns:
    182            The new subtree root after deletion.
    183
    184        Raises:
    185            ValueError: if value is not found.
    186        """
    187        if node is None:
    188            raise ValueError("Value not found in the tree")
    189            return None
    190
    191        if value < node.value:
    192            node.left = self.delete_node(node.left, value)
    193        elif value > node.value:
    194            node.right = self.delete_node(node.right, value)
    195        else:
    196            if node.left is None:
    197                subtree = node.right
    198                node = None
    199                return subtree
    200            elif node.right is None:
    201                subtree = node.left
    202                node = None
    203                return subtree
    204
    205            successor = self.successor_node(node.right)
    206            node.value = successor.value
    207            node.right = self.delete_node(node.right, successor.value)
    208
    209        return node
    210
    211    def successor_node(self, node=None):
    212        """
    213        Return the successor node (the minimum value in a binary search tree's right subtree).
    214
    215        Args:
    216            node: The starting node.
    217
    218        Returns:
    219            node with the lowest value in the BST
    220            None if not found
    221
    222        Raises:
    223            ValueError: if value is not found.
    224        """
    225        if node is None:
    226            node = self.root
    227
    228        if node.left is None:
    229            return node
    230        else:
    231            return self.successor_node(node.left)
    232
    233    def predecessor_node(self, node=None):
    234        """
    235        Return the predecessor node (the maximum value in a binary search tree's left subtree).
    236
    237        Args:
    238            node: The starting node.
    239
    240        Returns:
    241            node with the lowest value in the BST
    242            None if not found
    243
    244        Raises:
    245            ValueError: if value is not found.
    246        """
    247        if node is None:
    248            node = self.root
    249
    250        if node.right is None:
    251            return node
    252        else:
    253            return self.predecessor_node(node.right)
    254
    255    def delete_iterative(self, root, value):
    256        """
    257        Delete a value from the binary search tree (iterative version).
    258
    259        Args:
    260            value: The value to delete.
    261
    262        Returns:
    263            The root of the tree after insertion.
    264
    265
    266        Raises:
    267            ValueError: if value is not found.
    268        """
    269        parent = None
    270        current = root
    271
    272        # Find the node to delete and its parent
    273        while current and current.key != value:
    274            parent = current
    275            if value < current.key:
    276                current = current.left
    277            else:
    278                current = current.right
    279
    280        if current is None:
    281            return root  # Key not found
    282
    283        # Case 1 & 2: Node has at most one child
    284        def replace_node_in_parent(new_child):
    285            if parent is None:
    286                return new_child  # Deleting the root node
    287            if parent.left == current:
    288                parent.left = new_child
    289            else:
    290                parent.right = new_child
    291            return root
    292
    293        if current.left is None:
    294            return replace_node_in_parent(current.right)
    295        elif current.right is None:
    296            return replace_node_in_parent(current.left)
    297
    298        # Case 3: Node has two children
    299        # Find in-order successor and its parent
    300        successor_parent = current
    301        successor = current.right
    302        while successor.left:
    303            successor_parent = successor
    304            successor = successor.left
    305
    306        # Replace current's key with successor's key
    307        current.key = successor.key
    308
    309        # Delete successor node (which has at most one child)
    310        if successor_parent.left == successor:
    311            successor_parent.left = successor.right
    312        else:
    313            successor_parent.right = successor.right
    314
    315        return root
    316
    317    def print(self):
    318        """
    319        Print the values in the BST.
    320        """
    321        self.root.print()
    322
    323    def __len__(self):
    324        """
    325        Return the number of nodes in the BST.
    326
    327        Returns:
    328            The number of nodes in the BST.
    329        """
    330        def count_nodes(node):
    331            if node is None:
    332                return 0
    333            return 1 + count_nodes(node.left) + count_nodes(node.right)
    334
    335        return count_nodes(self.root)
    336

class TreeNode: View Source

     4class TreeNode:
     5    """
     6    A binary tree node implementation.
     7    """
     8    def __init__(self, value, left=None, right=None):
     9        """
    10        TreeNode constructor.
    11
    12        Args:
    13            value: The value of the node.
    14            left: Reference to the left node.
    15            right: Reference to the right node.
    16        """
    17        self.value = value
    18        self.left = left
    19        self.right = right
    20
    21    def copy(self):
    22        """
    23        Return a copy of the node.
    24        """
    25        new_node = TreeNode(self.value)
    26        if self.left:
    27            new_node.left = self.left.copy()
    28        if self.right:
    29            new_node.right = self.right.copy()
    30        return new_node
    31
    32    def print(self, level=0):
    33        """
    34        Print the contents of a node.
    35
    36        Args:
    37            level: starting level of node
    38        """
    39        if self.right:
    40            self.right.print(level + 1)
    41        print("   " * level + str(self.value))
    42        if self.left:
    43            self.left.print(level + 1)
    44
    45    def __lt__(self, other):
    46        """
    47        Compare the value of two nodes.
    48        """
    49        return self.value < other.value
    50
    51    def __repr__(self):
    52        """
    53        Return the string representation of a node.
    54        """
    55        if self.value is None:
    56            return "none"
    57        else:
    58            return str(self.value)

A binary tree node implementation.

TreeNode(value, left=None, right=None) View Source

     8    def __init__(self, value, left=None, right=None):
     9        """
    10        TreeNode constructor.
    11
    12        Args:
    13            value: The value of the node.
    14            left: Reference to the left node.
    15            right: Reference to the right node.
    16        """
    17        self.value = value
    18        self.left = left
    19        self.right = right

TreeNode constructor.

Args: value: The value of the node. left: Reference to the left node. right: Reference to the right node.

value
left
right
def copy(self): View Source

    21    def copy(self):
    22        """
    23        Return a copy of the node.
    24        """
    25        new_node = TreeNode(self.value)
    26        if self.left:
    27            new_node.left = self.left.copy()
    28        if self.right:
    29            new_node.right = self.right.copy()
    30        return new_node

Return a copy of the node.

def print(self, level=0): View Source

    32    def print(self, level=0):
    33        """
    34        Print the contents of a node.
    35
    36        Args:
    37            level: starting level of node
    38        """
    39        if self.right:
    40            self.right.print(level + 1)
    41        print("   " * level + str(self.value))
    42        if self.left:
    43            self.left.print(level + 1)

Print the contents of a node.

Args: level: starting level of node

class Tree: View Source

     60class Tree:
     61    """
     62    A binary search tree (BST) implementation. Can be treated as a plain binary tree if operations (insert, search, delete) are not used and nodes are set manually.
     63    """
     64    def __init__(self, root=None):
     65        """
     66        Args:
     67            root: Root node of the Tree.
     68        """
     69        self.root = root
     70
     71    def search(self, value):
     72        """
     73        Search for a value in the binary search tree.
     74
     75        Args:
     76            value: Value to search for.
     77
     78        Returns:
     79            node with matching value
     80
     81        Raises:
     82            ValueError: if value is not found
     83        """
     84        current = self.root
     85
     86        while current is not None:
     87            if value == current.value:
     88                return current
     89            elif value < current.value:
     90                current = current.left
     91            elif value > current.value:
     92                current = current.right
     93
     94        raise ValueError(f"Value {value} not found in the tree")
     95
     96    def insert(self, value):
     97        """
     98        Insert a value in the binary search tree.
     99
    100        Args:
    101            value: The value to insert.
    102
    103        Returns:
    104            The root of the tree after deletion.
    105
    106        Raises:
    107            ValueError: if value is already in the tree
    108        """
    109        self.root = self.insert_rec(self.root, value)
    110        return self.root
    111
    112    def insert_rec(self, root, value):
    113        if root is None:
    114            return TreeNode(value)
    115        if value < root.value:
    116            root.left = self.insert_rec(root.left, value)
    117        elif value > root.value:
    118            root.right = self.insert_rec(root.right, value)
    119        else:
    120            raise ValueError("Value already exists in the tree")
    121        return root
    122
    123    def insert_iterative(self, value):
    124        """
    125        Insert a value in the binary search tree (iterative implementation).
    126
    127        Args:
    128            value: The value to insert.
    129
    130        Returns:
    131            None
    132
    133        Raises:
    134            ValueError: if value is already in the tree
    135        """
    136        current = self.root
    137        if self.root is None:
    138            self.root = TreeNode(value)
    139            return
    140
    141        while current is not None:
    142            if value < current.value:
    143                if current.left is None:
    144                    current.left = TreeNode(value)
    145                    return
    146                else:
    147                    current = current.left
    148            elif value > current.value:
    149                if current.right is None:
    150                    current.right = TreeNode(value)
    151                    return
    152                else:
    153                    current = current.right
    154            else:
    155                return
    156
    157    def delete(self, value):
    158        """
    159        Delete a value from the binary search tree.
    160
    161        Args:
    162            value: The value to delete.
    163
    164        Returns:
    165            The root of the tree after insertion.
    166
    167
    168        Raises:
    169            ValueError: if value is not found.
    170        """
    171        self.root = self.delete_node(self.root, value)
    172        return self.root
    173
    174    def delete_node(self, node, value):
    175        """
    176        Helper function to delete a value from the binary search tree. (Use delete() instead)
    177
    178        Args:
    179            value: The value to delete.
    180            node: The current node.
    181
    182        Returns:
    183            The new subtree root after deletion.
    184
    185        Raises:
    186            ValueError: if value is not found.
    187        """
    188        if node is None:
    189            raise ValueError("Value not found in the tree")
    190            return None
    191
    192        if value < node.value:
    193            node.left = self.delete_node(node.left, value)
    194        elif value > node.value:
    195            node.right = self.delete_node(node.right, value)
    196        else:
    197            if node.left is None:
    198                subtree = node.right
    199                node = None
    200                return subtree
    201            elif node.right is None:
    202                subtree = node.left
    203                node = None
    204                return subtree
    205
    206            successor = self.successor_node(node.right)
    207            node.value = successor.value
    208            node.right = self.delete_node(node.right, successor.value)
    209
    210        return node
    211
    212    def successor_node(self, node=None):
    213        """
    214        Return the successor node (the minimum value in a binary search tree's right subtree).
    215
    216        Args:
    217            node: The starting node.
    218
    219        Returns:
    220            node with the lowest value in the BST
    221            None if not found
    222
    223        Raises:
    224            ValueError: if value is not found.
    225        """
    226        if node is None:
    227            node = self.root
    228
    229        if node.left is None:
    230            return node
    231        else:
    232            return self.successor_node(node.left)
    233
    234    def predecessor_node(self, node=None):
    235        """
    236        Return the predecessor node (the maximum value in a binary search tree's left subtree).
    237
    238        Args:
    239            node: The starting node.
    240
    241        Returns:
    242            node with the lowest value in the BST
    243            None if not found
    244
    245        Raises:
    246            ValueError: if value is not found.
    247        """
    248        if node is None:
    249            node = self.root
    250
    251        if node.right is None:
    252            return node
    253        else:
    254            return self.predecessor_node(node.right)
    255
    256    def delete_iterative(self, root, value):
    257        """
    258        Delete a value from the binary search tree (iterative version).
    259
    260        Args:
    261            value: The value to delete.
    262
    263        Returns:
    264            The root of the tree after insertion.
    265
    266
    267        Raises:
    268            ValueError: if value is not found.
    269        """
    270        parent = None
    271        current = root
    272
    273        # Find the node to delete and its parent
    274        while current and current.key != value:
    275            parent = current
    276            if value < current.key:
    277                current = current.left
    278            else:
    279                current = current.right
    280
    281        if current is None:
    282            return root  # Key not found
    283
    284        # Case 1 & 2: Node has at most one child
    285        def replace_node_in_parent(new_child):
    286            if parent is None:
    287                return new_child  # Deleting the root node
    288            if parent.left == current:
    289                parent.left = new_child
    290            else:
    291                parent.right = new_child
    292            return root
    293
    294        if current.left is None:
    295            return replace_node_in_parent(current.right)
    296        elif current.right is None:
    297            return replace_node_in_parent(current.left)
    298
    299        # Case 3: Node has two children
    300        # Find in-order successor and its parent
    301        successor_parent = current
    302        successor = current.right
    303        while successor.left:
    304            successor_parent = successor
    305            successor = successor.left
    306
    307        # Replace current's key with successor's key
    308        current.key = successor.key
    309
    310        # Delete successor node (which has at most one child)
    311        if successor_parent.left == successor:
    312            successor_parent.left = successor.right
    313        else:
    314            successor_parent.right = successor.right
    315
    316        return root
    317
    318    def print(self):
    319        """
    320        Print the values in the BST.
    321        """
    322        self.root.print()
    323
    324    def __len__(self):
    325        """
    326        Return the number of nodes in the BST.
    327
    328        Returns:
    329            The number of nodes in the BST.
    330        """
    331        def count_nodes(node):
    332            if node is None:
    333                return 0
    334            return 1 + count_nodes(node.left) + count_nodes(node.right)
    335
    336        return count_nodes(self.root)

A binary search tree (BST) implementation. Can be treated as a plain binary tree if operations (insert, search, delete) are not used and nodes are set manually.

Tree(root=None) View Source

    64    def __init__(self, root=None):
    65        """
    66        Args:
    67            root: Root node of the Tree.
    68        """
    69        self.root = root

Args: root: Root node of the Tree.

root
def search(self, value): View Source

    71    def search(self, value):
    72        """
    73        Search for a value in the binary search tree.
    74
    75        Args:
    76            value: Value to search for.
    77
    78        Returns:
    79            node with matching value
    80
    81        Raises:
    82            ValueError: if value is not found
    83        """
    84        current = self.root
    85
    86        while current is not None:
    87            if value == current.value:
    88                return current
    89            elif value < current.value:
    90                current = current.left
    91            elif value > current.value:
    92                current = current.right
    93
    94        raise ValueError(f"Value {value} not found in the tree")

Search for a value in the binary search tree.

Args: value: Value to search for.

Returns: node with matching value

Raises: ValueError: if value is not found

def insert(self, value): View Source

     96    def insert(self, value):
     97        """
     98        Insert a value in the binary search tree.
     99
    100        Args:
    101            value: The value to insert.
    102
    103        Returns:
    104            The root of the tree after deletion.
    105
    106        Raises:
    107            ValueError: if value is already in the tree
    108        """
    109        self.root = self.insert_rec(self.root, value)
    110        return self.root

Insert a value in the binary search tree.

Args: value: The value to insert.

Returns: The root of the tree after deletion.

Raises: ValueError: if value is already in the tree

def insert_rec(self, root, value): View Source

    112    def insert_rec(self, root, value):
    113        if root is None:
    114            return TreeNode(value)
    115        if value < root.value:
    116            root.left = self.insert_rec(root.left, value)
    117        elif value > root.value:
    118            root.right = self.insert_rec(root.right, value)
    119        else:
    120            raise ValueError("Value already exists in the tree")
    121        return root

def insert_iterative(self, value): View Source

    123    def insert_iterative(self, value):
    124        """
    125        Insert a value in the binary search tree (iterative implementation).
    126
    127        Args:
    128            value: The value to insert.
    129
    130        Returns:
    131            None
    132
    133        Raises:
    134            ValueError: if value is already in the tree
    135        """
    136        current = self.root
    137        if self.root is None:
    138            self.root = TreeNode(value)
    139            return
    140
    141        while current is not None:
    142            if value < current.value:
    143                if current.left is None:
    144                    current.left = TreeNode(value)
    145                    return
    146                else:
    147                    current = current.left
    148            elif value > current.value:
    149                if current.right is None:
    150                    current.right = TreeNode(value)
    151                    return
    152                else:
    153                    current = current.right
    154            else:
    155                return

Insert a value in the binary search tree (iterative implementation).

Args: value: The value to insert.

Returns: None

Raises: ValueError: if value is already in the tree

def delete(self, value): View Source

    157    def delete(self, value):
    158        """
    159        Delete a value from the binary search tree.
    160
    161        Args:
    162            value: The value to delete.
    163
    164        Returns:
    165            The root of the tree after insertion.
    166
    167
    168        Raises:
    169            ValueError: if value is not found.
    170        """
    171        self.root = self.delete_node(self.root, value)
    172        return self.root

Delete a value from the binary search tree.

Args: value: The value to delete.

Returns: The root of the tree after insertion.

Raises: ValueError: if value is not found.

def delete_node(self, node, value): View Source

    174    def delete_node(self, node, value):
    175        """
    176        Helper function to delete a value from the binary search tree. (Use delete() instead)
    177
    178        Args:
    179            value: The value to delete.
    180            node: The current node.
    181
    182        Returns:
    183            The new subtree root after deletion.
    184
    185        Raises:
    186            ValueError: if value is not found.
    187        """
    188        if node is None:
    189            raise ValueError("Value not found in the tree")
    190            return None
    191
    192        if value < node.value:
    193            node.left = self.delete_node(node.left, value)
    194        elif value > node.value:
    195            node.right = self.delete_node(node.right, value)
    196        else:
    197            if node.left is None:
    198                subtree = node.right
    199                node = None
    200                return subtree
    201            elif node.right is None:
    202                subtree = node.left
    203                node = None
    204                return subtree
    205
    206            successor = self.successor_node(node.right)
    207            node.value = successor.value
    208            node.right = self.delete_node(node.right, successor.value)
    209
    210        return node

Helper function to delete a value from the binary search tree. (Use delete() instead)

Args: value: The value to delete. node: The current node.

Returns: The new subtree root after deletion.

Raises: ValueError: if value is not found.

def successor_node(self, node=None): View Source

    212    def successor_node(self, node=None):
    213        """
    214        Return the successor node (the minimum value in a binary search tree's right subtree).
    215
    216        Args:
    217            node: The starting node.
    218
    219        Returns:
    220            node with the lowest value in the BST
    221            None if not found
    222
    223        Raises:
    224            ValueError: if value is not found.
    225        """
    226        if node is None:
    227            node = self.root
    228
    229        if node.left is None:
    230            return node
    231        else:
    232            return self.successor_node(node.left)

Return the successor node (the minimum value in a binary search tree's right subtree).

Args: node: The starting node.

Returns: node with the lowest value in the BST None if not found

Raises: ValueError: if value is not found.

def predecessor_node(self, node=None): View Source

    234    def predecessor_node(self, node=None):
    235        """
    236        Return the predecessor node (the maximum value in a binary search tree's left subtree).
    237
    238        Args:
    239            node: The starting node.
    240
    241        Returns:
    242            node with the lowest value in the BST
    243            None if not found
    244
    245        Raises:
    246            ValueError: if value is not found.
    247        """
    248        if node is None:
    249            node = self.root
    250
    251        if node.right is None:
    252            return node
    253        else:
    254            return self.predecessor_node(node.right)

Return the predecessor node (the maximum value in a binary search tree's left subtree).

Args: node: The starting node.

Returns: node with the lowest value in the BST None if not found

Raises: ValueError: if value is not found.

def delete_iterative(self, root, value): View Source

    256    def delete_iterative(self, root, value):
    257        """
    258        Delete a value from the binary search tree (iterative version).
    259
    260        Args:
    261            value: The value to delete.
    262
    263        Returns:
    264            The root of the tree after insertion.
    265
    266
    267        Raises:
    268            ValueError: if value is not found.
    269        """
    270        parent = None
    271        current = root
    272
    273        # Find the node to delete and its parent
    274        while current and current.key != value:
    275            parent = current
    276            if value < current.key:
    277                current = current.left
    278            else:
    279                current = current.right
    280
    281        if current is None:
    282            return root  # Key not found
    283
    284        # Case 1 & 2: Node has at most one child
    285        def replace_node_in_parent(new_child):
    286            if parent is None:
    287                return new_child  # Deleting the root node
    288            if parent.left == current:
    289                parent.left = new_child
    290            else:
    291                parent.right = new_child
    292            return root
    293
    294        if current.left is None:
    295            return replace_node_in_parent(current.right)
    296        elif current.right is None:
    297            return replace_node_in_parent(current.left)
    298
    299        # Case 3: Node has two children
    300        # Find in-order successor and its parent
    301        successor_parent = current
    302        successor = current.right
    303        while successor.left:
    304            successor_parent = successor
    305            successor = successor.left
    306
    307        # Replace current's key with successor's key
    308        current.key = successor.key
    309
    310        # Delete successor node (which has at most one child)
    311        if successor_parent.left == successor:
    312            successor_parent.left = successor.right
    313        else:
    314            successor_parent.right = successor.right
    315
    316        return root

Delete a value from the binary search tree (iterative version).

Args: value: The value to delete.

Returns: The root of the tree after insertion.

Raises: ValueError: if value is not found.

def print(self): View Source

    318    def print(self):
    319        """
    320        Print the values in the BST.
    321        """
    322        self.root.print()

Print the values in the BST.