AlgoDatSoSe26/praktika/04_bin_baum/aufgabe5_analyse.py
2026-05-11 15:31:57 +02:00

86 lines
3.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '..'))
import random
from utils.algo_context import AlgoContext
from vorlesung.L05_binaere_baeume.bin_tree import BinaryTree
from vorlesung.L05_binaere_baeume.avl_tree import AVLTree
# ── Theoretische Herleitung ───────────────────────────────────────────────────
# AVL-Baum / ausgeglichener BST
# Bei jedem Schritt der Suche wird genau ein Teilbaum mit (ungefähr) halber
# Größe weiterverfolgt:
#
# T(n) = T(n/2) + O(1)
#
# Master-Theorem: a=1, b=2, f(n)=O(1)
# log_b(a) = log_2(1) = 0 → f(n) = O(n^0) = O(n^log_b(a))
# → Fall 2: T(n) = O(log n)
# BST Worst Case (sortierte Eingabe, entarteter Baum)
# Der Baum ist eine verkettete Liste; jeder Schritt reduziert das Problem um 1:
#
# T(n) = T(n-1) + O(1)
#
# Kein Master-Theorem (b > 1 gefordert). Direkte Auflösung durch Entfalten:
# T(n) = T(n-2) + 2·c = … = T(0) + n·c → O(n)
# BST zufällige Eingabe (Expected Case)
# Bei zufälliger Einfügereihenfolge teilt die Wurzel den Schlüsselraum im
# Erwartungswert in zwei ungefähr gleich große Hälften analog zum
# durchschnittlichen Fall bei Quicksort. Daraus folgt eine erwartete Höhe
# von O(log n), empirisch ca. 2,5 · log₂(n). Ein formaler Beweis erfordert
# eine Wahrscheinlichkeitsanalyse über alle n! Permutationen.
# ── Empirische Messung ───────────────────────────────────────────────────────
SIZES = [10, 100, 500]
print(f"{'n':>5} {'BST zufällig':>14} {'BST sortiert':>14} {'AVL sortiert':>14}")
print("-" * 55)
for n in SIZES:
# BST, zufällige Eingabe
ctx = AlgoContext()
tree = BinaryTree(ctx)
values = random.sample(range(n * 10), n)
for v in values:
tree.insert(v)
ctx.comparisons = 0
tree.search(values[-1])
cmp_random = ctx.comparisons
# BST, sortierte Eingabe
ctx = AlgoContext()
tree = BinaryTree(ctx)
for v in range(1, n + 1):
tree.insert(v)
ctx.comparisons = 0
tree.search(n)
cmp_sorted = ctx.comparisons
# AVL-Baum, sortierte Eingabe
ctx = AlgoContext()
tree = AVLTree(ctx)
for v in range(1, n + 1):
tree.insert(v)
ctx.comparisons = 0
tree.search(n)
cmp_avl = ctx.comparisons
print(f"{n:>5} {cmp_random:>14} {cmp_sorted:>14} {cmp_avl:>14}")
# ── Abschlussfrage ────────────────────────────────────────────────────────────
#
# Stimmen die Messwerte mit den theoretischen Komplexitätsklassen überein?
#
# BST sortiert wächst linear mit n (2·n Vergleiche für das letzte Element),
# was die hergeleitete O(n)-Komplexität bestätigt.
#
# BST zufällig und AVL sortiert wachsen logarithmisch: für n=500 liegen die
# Vergleiche bei ca. 20 bzw. 18 weit unter dem linearen Worst Case.
# Das bestätigt O(log n) für beide, wobei der AVL-Baum die Schranke
# garantiert und der zufällige BST sie nur im Erwartungswert einhält.