class BSTNode:
def __init__(self, key, value=None):
self.key = key
self.value = value
self.parent = None
self.left = None
self.right = None
def __str__(self):
= str(self.key)
key = 'None' if self.parent is None else str(self.parent.key)
parent = 'None' if self.left is None else str(self.left.key)
left = 'None' if self.right is None else str(self.right.key)
right = (
s f'\tParent = {parent}\n'
f'\tKey = {key}\n'
f'Left = {left}\tRight = {right}'
)return s
Binary Search Tree
Ein binärer Suchbaum (Binary Search Tree, BST) ist eine Datenstruktur, die es ermöglicht, Daten in einer hierarchischen Struktur zu speichern. Jeder Knoten im Baum hat maximal zwei Kinder, wobei das linke Kind kleiner und das rechte Kind grösser als der Knoten selbst ist. Dies ermöglicht das effiziente Suchen, Einfügen und Löschen von Elementen.
Sollen beispielsweise die Zahlen 42, 23, 17, 34, 56, 78 und 12 der Reihe nach in einen binären Suchbaum eingefügt werden, geschieht dies wie folgt:
42
/ \
23 56
/ \ \
17 34 78
/
12
Um einen Knoten zu löschen, gibt es drei Fälle zu beachten: 1. Der Knoten ist ein Blatt (keine Kinder): Der Knoten kann einfach entfernt werden. 2. Der Knoten hat ein Kind: Das Kind ersetzt den Knoten. 3. Der Knoten hat zwei Kinder: Der Knoten wird durch den kleinsten Knoten im rechten Teilbaum ersetzt.
In den folgenden Abschnitten findet sich eine Mögliche Implementierung eines binären Suchbaums in Python.
Klasse BSTNode
Klasse BST
class BST:
def __init__(self, key=None, value=None):
if key is None:
self.root = None
else:
= BSTNode(key, value)
node self.root = node
def insert(self, key, value=None, root=None):
= BSTNode(key, value)
node if self.root is None:
self.root = node
return
if root is None:
= self.root
root
if key < root.key and root.left is None:
= node
root.left = root
node.parent return
if key < root.key:
= root.left
root self.insert(key, value, root)
if key > root.key and root.right is None:
= node
root.right = root
node.parent return
if key > root.key:
= root.right
root self.insert(key, value, root)
def min(self, bst=None):
if bst is None:
= self.root
minimum else:
=bst.root
minimum
while minimum.left is not None:
= minimum.left
minimum
return minimum
def max(self, bst=None):
if bst is None:
= self.root
maximum else:
= bst.root
maximum
while maximum.right is not None:
= maximum.right
maximum
return maximum
def search(self, key, node=None):
# If initial call or we've hit None in recursion
if node is None:
if self.root is None: # Empty tree
return -1
= self.root
node
# Found the key
if key == node.key:
return node
# Key doesn't exist in this path
if key < node.key:
if node.left is None:
return -1
return self.search(key, node.left)
else: # key > node.key
if node.right is None:
return -1
return self.search(key, node.right)
def delete(self, key):
# Find the node to delete
= self.search(key)
node
# If node not found, return
if node == -1:
return
self._delete_node(node)
def _delete_node(self, node):
# Case 1: Node has no children (leaf node)
if node.left is None and node.right is None:
if node == self.root:
self.root = None
else:
if node.parent.left == node:
= None
node.parent.left else:
= None
node.parent.right
# Case 2: Node has only one child
elif node.left is None: # Has only right child
if node == self.root:
self.root = node.right
= None
node.right.parent else:
if node.parent.left == node:
= node.right
node.parent.left else:
= node.right
node.parent.right = node.parent
node.right.parent
elif node.right is None: # Has only left child
if node == self.root:
self.root = node.left
= None
node.left.parent else:
if node.parent.left == node:
= node.left
node.parent.left else:
= node.left
node.parent.right = node.parent
node.left.parent
# Case 3: Node has two children
else:
# Find successor (smallest node in right subtree)
= None
successor = node.right
current
while current.left is not None:
= current.left
current
= current
successor
# Copy successor's key and value to the node
= successor.key
node.key = successor.value
node.value
# Delete the successor (which has at most one right child)
self._delete_node(successor)
def iterate(self, node=None, result=None):
# Initialize result list on first call
if result is None:
= []
result
# Use root if no starting node provided
if node is None:
if self.root is None: # Empty tree
return result
= self.root
node
# In-order traversal: left -> current -> right
if node.left is not None:
self.iterate(node.left, result)
result.append(node)
if node.right is not None:
self.iterate(node.right, result)
return result