forked from hofmannol/AlgoDatSoSe25
merge upstream
This commit is contained in:
commit
1985a2a4a3
8
data/hoehle.txt
Normal file
8
data/hoehle.txt
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
"Höhleneingang" <> "Ost/West-Passage"
|
||||||
|
"Höhleneingang" <> "Nord/Süd-Passage"
|
||||||
|
"Nord/Süd-Passage" <> "Nebelraum"
|
||||||
|
"Steiniger Pfad" > "Ost/West-Passage"
|
||||||
|
"Ost/West-Passage" <> "Schwefelgewölbe"
|
||||||
|
"Schwefelgewölbe" > "Steiniger Pfad"
|
||||||
|
"Schatzkammer" > "Nebelraum"
|
||||||
|
"Steiniger Pfad" > "Schatzkammer"
|
124
praktika/07_hashtable/praktikum.py
Normal file
124
praktika/07_hashtable/praktikum.py
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
import math
|
||||||
|
import unittest
|
||||||
|
from utils.literal import Literal
|
||||||
|
from utils.memory_cell import MemoryCell
|
||||||
|
from utils.memory_array import MemoryArray
|
||||||
|
from vorlesung.L07_hashtable.hashtable import HashTableOpenAddressing
|
||||||
|
|
||||||
|
#Goldener Schnitt
|
||||||
|
a = Literal((math.sqrt(5) - 1) / 2)
|
||||||
|
|
||||||
|
# Hashfunktion nach multiplikativer Methode
|
||||||
|
def h(x: MemoryCell, m: Literal) -> Literal:
|
||||||
|
with MemoryCell(int(x * a)) as integer_part, MemoryCell(x * a) as full_product:
|
||||||
|
with MemoryCell(full_product - integer_part) as fractional_part:
|
||||||
|
return Literal(abs(int(fractional_part * m)))
|
||||||
|
|
||||||
|
# Quadratische Sondierung
|
||||||
|
def f(x: MemoryCell, i: Literal, m: Literal) -> Literal:
|
||||||
|
c1 = 1
|
||||||
|
c2 = 5
|
||||||
|
with MemoryCell(h(x, m)) as initial_hash, MemoryCell(c2 * int(i) * int(i)) as quadratic_offset:
|
||||||
|
with MemoryCell(initial_hash + quadratic_offset) as probe_position:
|
||||||
|
probe_position += Literal(c1 * int(i)) # Linear component
|
||||||
|
return probe_position % m
|
||||||
|
|
||||||
|
# Symmetrische quadratische Sondierung
|
||||||
|
def fs(x: MemoryCell, i: Literal, m: Literal) -> Literal:
|
||||||
|
with MemoryCell(h(x, m)) as base_hash, MemoryCell(int(i) * int(i)) as square:
|
||||||
|
if int(i) % 2 == 0: # gerades i: Vorwärtssondierung
|
||||||
|
with MemoryCell(base_hash + square) as position:
|
||||||
|
return position % m
|
||||||
|
else: # ungerades i: Rückwärtssondierung
|
||||||
|
with MemoryCell(base_hash - square) as position:
|
||||||
|
return position % m
|
||||||
|
|
||||||
|
|
||||||
|
class TestHashTableOpenAddressing(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_hash_function(self):
|
||||||
|
x = MemoryCell(22)
|
||||||
|
m = Literal(20)
|
||||||
|
self.assertEqual(11, h(x, m).value)
|
||||||
|
|
||||||
|
def test_probe_function(self):
|
||||||
|
x = MemoryCell(22)
|
||||||
|
i = Literal(0)
|
||||||
|
m = Literal(20)
|
||||||
|
self.assertEqual(11, f(x, i, m).value)
|
||||||
|
i = Literal(1)
|
||||||
|
self.assertEqual(17, f(x, i, m).value)
|
||||||
|
i = Literal(2)
|
||||||
|
self.assertEqual(13, f(x, i, m).value)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
#unittest.main()
|
||||||
|
|
||||||
|
print("*** Aufgabe 3 ***")
|
||||||
|
size = Literal(20)
|
||||||
|
print(f"Anlage einer Hash-Tabelle mit offener Adressierung mit Größe {size}")
|
||||||
|
ht = HashTableOpenAddressing(size, f)
|
||||||
|
print("Einfügen der Werte aus seq0.txt")
|
||||||
|
for cell in MemoryArray.create_array_from_file("data/seq0.txt"):
|
||||||
|
if not ht.insert(cell):
|
||||||
|
print(f"Einfügen von {cell} nicht möglich")
|
||||||
|
print(ht)
|
||||||
|
print(f"Belegungsfaktor: {ht.alpha()}")
|
||||||
|
|
||||||
|
with MemoryCell(52) as cell:
|
||||||
|
print(f"Suche nach {cell}")
|
||||||
|
if ht.search(cell):
|
||||||
|
print(f"{cell} gefunden, wird gelöscht.")
|
||||||
|
ht.delete(cell)
|
||||||
|
else:
|
||||||
|
print(f"{cell} nicht gefunden")
|
||||||
|
print(ht)
|
||||||
|
print(f"Belegungsfaktor: {ht.alpha()}")
|
||||||
|
print("Einfügen von 24")
|
||||||
|
with MemoryCell(24) as cell:
|
||||||
|
if not ht.insert(cell):
|
||||||
|
print(f"Einfügen von {cell} nicht möglich")
|
||||||
|
print(ht)
|
||||||
|
print(f"Belegungsfaktor: {ht.alpha()}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
print("*** Aufgabe 4 ***")
|
||||||
|
size = Literal(90)
|
||||||
|
print(f"Anlage einer Hash-Tabelle mit offener Adressierung mit Größe {size}")
|
||||||
|
ht = HashTableOpenAddressing(size, f)
|
||||||
|
print("Einfügen der Werte aus seq1.txt")
|
||||||
|
for cell in MemoryArray.create_array_from_file("data/seq1.txt"):
|
||||||
|
if not ht.insert(cell):
|
||||||
|
print(f"Einfügen von {cell} nicht möglich")
|
||||||
|
print(ht)
|
||||||
|
print(f"Belegungsfaktor: {ht.alpha()}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
print("*** Aufgabe 5 ***")
|
||||||
|
size = Literal(89)
|
||||||
|
print(f"Anlage einer Hash-Tabelle mit offener Adressierung mit Größe {size}")
|
||||||
|
ht = HashTableOpenAddressing(size, f)
|
||||||
|
print("Einfügen der Werte aus seq1.txt")
|
||||||
|
for cell in MemoryArray.create_array_from_file("data/seq1.txt"):
|
||||||
|
if not ht.insert(cell):
|
||||||
|
print(f"Einfügen von {cell} nicht möglich")
|
||||||
|
print(ht)
|
||||||
|
print(f"Belegungsfaktor: {ht.alpha()}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
print("*** Aufgabe 6 ***")
|
||||||
|
size = Literal(90)
|
||||||
|
print(f"Anlage einer Hash-Tabelle mit offener Adressierung mit Größe {size}")
|
||||||
|
print("Verwendung der symmetrischen quadratischen Sondierung")
|
||||||
|
ht = HashTableOpenAddressing(size, fs)
|
||||||
|
print("Einfügen der Werte aus seq1.txt")
|
||||||
|
for cell in MemoryArray.create_array_from_file("data/seq1.txt"):
|
||||||
|
if not ht.insert(cell):
|
||||||
|
print(f"Einfügen von {cell} nicht möglich")
|
||||||
|
print(ht)
|
||||||
|
print(f"Belegungsfaktor: {ht.alpha()}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
|
0
vorlesung/L07_hashtable/__init__.py
Normal file
0
vorlesung/L07_hashtable/__init__.py
Normal file
60
vorlesung/L07_hashtable/analyze_hashtable.py
Normal file
60
vorlesung/L07_hashtable/analyze_hashtable.py
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import math
|
||||||
|
import random
|
||||||
|
from utils.literal import Literal
|
||||||
|
from utils.memory_cell import MemoryCell
|
||||||
|
from utils.memory_array import MemoryArray
|
||||||
|
from utils.memory_manager import MemoryManager
|
||||||
|
from vorlesung.L07_hashtable.hashtable import HashTableOpenAddressing
|
||||||
|
|
||||||
|
#Goldener Schnitt
|
||||||
|
a = Literal((math.sqrt(5) - 1) / 2)
|
||||||
|
|
||||||
|
# Hashfunktion nach multiplikativer Methode
|
||||||
|
def h(x: MemoryCell, m: Literal) -> Literal:
|
||||||
|
with MemoryCell(int(x * a)) as integer_part, MemoryCell(x * a) as full_product:
|
||||||
|
with MemoryCell(full_product - integer_part) as fractional_part:
|
||||||
|
return Literal(abs(int(fractional_part * m)))
|
||||||
|
|
||||||
|
# Quadratische Sondierung
|
||||||
|
def f(x: MemoryCell, i: Literal, m: Literal) -> Literal:
|
||||||
|
c1 = 1
|
||||||
|
c2 = 5
|
||||||
|
with MemoryCell(h(x, m)) as initial_hash, MemoryCell(c2 * int(i) * int(i)) as quadratic_offset:
|
||||||
|
with MemoryCell(initial_hash + quadratic_offset) as probe_position:
|
||||||
|
probe_position += Literal(c1 * int(i)) # Linear component
|
||||||
|
return probe_position % m
|
||||||
|
|
||||||
|
# Symmetrische quadratische Sondierung
|
||||||
|
def fs(x: MemoryCell, i: Literal, m: Literal) -> Literal:
|
||||||
|
with MemoryCell(h(x, m)) as base_hash, MemoryCell(int(i) * int(i)) as square:
|
||||||
|
if int(i) % 2 == 0: # gerades i: Vorwärtssondierung
|
||||||
|
with MemoryCell(base_hash + square) as position:
|
||||||
|
return position % m
|
||||||
|
else: # ungerades i: Rückwärtssondierung
|
||||||
|
with MemoryCell(base_hash - square) as position:
|
||||||
|
return position % m
|
||||||
|
|
||||||
|
|
||||||
|
def analyze_complexity(sizes):
|
||||||
|
"""
|
||||||
|
Analysiert die Komplexität
|
||||||
|
|
||||||
|
:param sizes: Eine Liste von Eingabegrößen für die Analyse.
|
||||||
|
"""
|
||||||
|
for size in sizes:
|
||||||
|
MemoryManager.purge() # Speicher zurücksetzen
|
||||||
|
ht = HashTableOpenAddressing(size, f)
|
||||||
|
random_array = MemoryArray.create_random_array(size, -100, 100)
|
||||||
|
for cell in random_array:
|
||||||
|
ht.insert(cell)
|
||||||
|
MemoryManager.reset()
|
||||||
|
cell = random.choice(random_array.cells)
|
||||||
|
ht.search(cell)
|
||||||
|
MemoryManager.save_stats(size)
|
||||||
|
|
||||||
|
MemoryManager.plot_stats(["cells", "compares"])
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sizes = range(1, 1001, 10)
|
||||||
|
analyze_complexity(sizes)
|
76
vorlesung/L07_hashtable/hashtable.py
Normal file
76
vorlesung/L07_hashtable/hashtable.py
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
from collections.abc import Callable
|
||||||
|
from utils.literal import Literal
|
||||||
|
from utils.memory_array import MemoryArray
|
||||||
|
from utils.memory_cell import MemoryCell
|
||||||
|
from utils.memory_range import mrange
|
||||||
|
|
||||||
|
|
||||||
|
UNUSED_MARK = "UNUSED"
|
||||||
|
DELETED_MARK = "DELETED"
|
||||||
|
|
||||||
|
class HashTableOpenAddressing:
|
||||||
|
def __init__(self, m: Literal, f: Callable[[MemoryCell, Literal, Literal], Literal]):
|
||||||
|
if not isinstance(m, Literal):
|
||||||
|
m = Literal(m)
|
||||||
|
self.m = m
|
||||||
|
self.f = f
|
||||||
|
self.table = MemoryArray(m)
|
||||||
|
for i in mrange(m):
|
||||||
|
self.table[i].value = UNUSED_MARK
|
||||||
|
|
||||||
|
def insert(self, x: MemoryCell):
|
||||||
|
with MemoryCell(0) as i:
|
||||||
|
while i < self.m:
|
||||||
|
j = self.f(x, i, self.m)
|
||||||
|
if self.is_free(j):
|
||||||
|
self.table[j].set(x)
|
||||||
|
return True
|
||||||
|
i.set(i.succ())
|
||||||
|
return False
|
||||||
|
|
||||||
|
def search(self, x: MemoryCell):
|
||||||
|
with MemoryCell(0) as i:
|
||||||
|
while i < self.m:
|
||||||
|
j = self.f(x, i, self.m)
|
||||||
|
if self.is_unused(j):
|
||||||
|
return False
|
||||||
|
if self.table[j] == x:
|
||||||
|
return True
|
||||||
|
i.set(i.succ())
|
||||||
|
return False
|
||||||
|
|
||||||
|
def delete(self, x: MemoryCell):
|
||||||
|
with MemoryCell(0) as i:
|
||||||
|
while i < self.m:
|
||||||
|
j = self.f(x, i, self.m)
|
||||||
|
if self.is_unused(j):
|
||||||
|
return False
|
||||||
|
if self.table[j] == x:
|
||||||
|
self.table[j].value = DELETED_MARK
|
||||||
|
return True
|
||||||
|
i.set(i.succ())
|
||||||
|
return False
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return str(self.table)
|
||||||
|
|
||||||
|
def alpha(self):
|
||||||
|
with MemoryCell(0) as i:
|
||||||
|
used = 0
|
||||||
|
while i < self.m:
|
||||||
|
used += 0 if self.is_free(i) else 1
|
||||||
|
i.set(i.succ())
|
||||||
|
return used / int(self.m)
|
||||||
|
|
||||||
|
def is_unused(self, i: Literal):
|
||||||
|
if self.table[i].value == UNUSED_MARK:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def is_deleted(self, i: Literal):
|
||||||
|
if self.table[i].value == DELETED_MARK:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def is_free(self, i: Literal):
|
||||||
|
return self.is_unused(i) or self.is_deleted(i)
|
Loading…
x
Reference in New Issue
Block a user