added BST, but remove not working

This commit is contained in:
2024-02-15 04:40:13 +01:00
parent 4c5d27e8d1
commit c7c1f3ea98
4 changed files with 113 additions and 61 deletions

View File

@ -84,4 +84,12 @@ Mit `yield from ...` kann man einen ganzen Iterator *yield*en.
```python ```python
def my_range(start: int, end: int) -> Iterator[int]: def my_range(start: int, end: int) -> Iterator[int]:
yield from range(start, end) yield from range(start, end)
``` ```
## [BinarySearchTree](./search_trees.py) (*Schwer*)
Was wäre wenn wir nun einen Binary Tree haben, dieser aber eine Sortierung hat. Wenn wir ein Element hinzufügen packen wir alle Elemente kleiner nach Links und alle anderen nach Rechts.
[Hier eine kleine Visualisierung](https://www.cs.usfca.edu/~galles/visualization/BST.html)
Probiert einfach mal rum damit ihr euch die Funktion eines BST vorstellen könnt. Wirklich komplex wird `delete`.

View File

@ -0,0 +1,13 @@
from typing import Optional
from trees import Node
type BinarySearchTree[T] = Optional[Node[T]]
def insert[T](node: BinarySearchTree[T], value: T) -> BinarySearchTree[T]:
pass
def exists[T](node: Optional[Node[T]], value: T) -> bool:
pass
def remove[T](node: BinarySearchTree[T], value: T) -> BinarySearchTree[T]:
pass

View File

@ -1,45 +1,49 @@
from typing import Iterator, Optional from typing import Optional
from trees import Node, traverse from trees import Node
from dataclasses import InitVar, dataclass
@dataclass type BinarySearchTree[T] = Optional[Node[T]]
class BinarySearchTree[T]:
def __post_init__(self): def insert[T](node: BinarySearchTree[T], value: T) -> BinarySearchTree[T]:
self.__root: Optional[Node[T]] = None prev = None
curr = node
while curr:
def insert(self, value: T): prev = curr
prev = None if curr.value > value:
curr = self.__root curr = curr.left
while curr:
prev = curr
if curr.value > value:
curr = curr.left
else:
curr = curr.right
if prev is None:
self.__root = Node(value, None, None)
elif value < prev.value:
prev.left = Node(value, None, None)
else: else:
prev.right = Node(value, None, None) curr = curr.right
if prev is None:
def __delete(prev: Node[T], to_delete: Node[T]) -> Node[T]: return Node(value, None, None)
# TODO: implement elif value < prev.value:
pass prev.left = Node(value, None, None)
else:
def remove(self, value: T): prev.right = Node(value, None, None)
prev = None return node
curr = self.__root
while curr:
prev = curr def exists[T](node: Optional[Node[T]], value: T) -> bool:
if curr.value > value: return node and (exists(node.left, value)
curr = curr.left if value < node.value
elif curr.value < value: else (value == node.value or exists(node.right, value)))
curr = curr.right
else:
curr = self.__delete(prev, curr) def remove[T](node: BinarySearchTree[T], value: T) -> BinarySearchTree[T]:
if node is None:
def __iter__(self) -> Iterator[T]: return node
yield from traverse(self.__root) if value < node.value:
node.left = remove(node.left, value)
return node
if value > node.value:
node.right = remove(node.right, value)
return node
if node.right is None:
return node.left
if node.left is None:
return node.right
min_node = node.right
while min_node.left:
min_node = min_node.left
node.value = min_node.value
node.right = remove(node.right, min_node.value)
return node

View File

@ -1,24 +1,51 @@
from search_trees import BinarySearchTree from typing import Iterator, Optional
from search_trees import BinarySearchTree, insert, remove, exists
from trees import Node
from random import randint as random from random import randint as random
MAX= 1000
def traverse[T](tree: Optional[Node[T]]) -> Iterator[T]:
match tree:
case Node(value, left, right):
yield from traverse(left)
yield value
yield from traverse(right)
case _:
return
MAX = 100
MIN = 0 MIN = 0
LENGTH = 100 LENGTH = 100
NUMS = {random(MIN, MAX) for _ in range(0, LENGTH)}
NUMS_FILTER = {random(MIN, MAX) for _ in range(0, LENGTH // 4)}
def test_insert(): def test_insert():
nums = [random(MIN, MAX) for _ in range(0, LENGTH)] bst: BinarySearchTree = None
bst = BinarySearchTree() for num in NUMS:
for num in nums: bst = insert(bst, num)
bst.insert(num) assert list(traverse(bst)) == sorted(NUMS)
assert list(iter(bst)) == sorted(nums)
def test_remove(): def test_remove():
nums = {random(MIN, MAX) for _ in range(0, LENGTH)} bst: BinarySearchTree = None
fil = {random(MIN, MAX) for _ in range(0, LENGTH // 4)} for num in NUMS:
bst = BinarySearchTree() bst = insert(bst, num)
for num in nums: assert list(traverse(bst)) == sorted(NUMS)
bst.insert(num) for num in NUMS_FILTER:
for num in fil: remove(bst, num)
bst.remove(num)
assert list(traverse(bst)) == sorted(filter(lambda x: x not in NUMS_FILTER, NUMS))
assert list(iter(bst)) == sorted(filter(lambda x: x not in fil, nums))
def test_exists():
bst: BinarySearchTree = None
for num in NUMS:
bst = insert(bst, num)
for num in NUMS_FILTER:
remove(bst, num)
assert all(map(lambda x: exists(bst, x),
filter(lambda x: x not in NUMS_FILTER, NUMS)))
assert all(map(lambda x: not exists(bst, x), NUMS_FILTER))