added BST, but remove not working
This commit is contained in:
@ -85,3 +85,11 @@ Mit `yield from ...` kann man einen ganzen Iterator *yield*en.
|
|||||||
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`.
|
13
recursion/recursive_datastructure/search_trees.py
Normal file
13
recursion/recursive_datastructure/search_trees.py
Normal 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
|
@ -1,17 +1,12 @@
|
|||||||
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):
|
|
||||||
self.__root: Optional[Node[T]] = None
|
|
||||||
|
|
||||||
|
|
||||||
def insert(self, value: T):
|
def insert[T](node: BinarySearchTree[T], value: T) -> BinarySearchTree[T]:
|
||||||
prev = None
|
prev = None
|
||||||
curr = self.__root
|
curr = node
|
||||||
while curr:
|
while curr:
|
||||||
prev = curr
|
prev = curr
|
||||||
if curr.value > value:
|
if curr.value > value:
|
||||||
@ -19,27 +14,36 @@ class BinarySearchTree[T]:
|
|||||||
else:
|
else:
|
||||||
curr = curr.right
|
curr = curr.right
|
||||||
if prev is None:
|
if prev is None:
|
||||||
self.__root = Node(value, None, None)
|
return Node(value, None, None)
|
||||||
elif value < prev.value:
|
elif value < prev.value:
|
||||||
prev.left = Node(value, None, None)
|
prev.left = Node(value, None, None)
|
||||||
else:
|
else:
|
||||||
prev.right = Node(value, None, None)
|
prev.right = Node(value, None, None)
|
||||||
|
return node
|
||||||
|
|
||||||
def __delete(prev: Node[T], to_delete: Node[T]) -> Node[T]:
|
|
||||||
# TODO: implement
|
|
||||||
pass
|
|
||||||
|
|
||||||
def remove(self, value: T):
|
def exists[T](node: Optional[Node[T]], value: T) -> bool:
|
||||||
prev = None
|
return node and (exists(node.left, value)
|
||||||
curr = self.__root
|
if value < node.value
|
||||||
while curr:
|
else (value == node.value or exists(node.right, value)))
|
||||||
prev = curr
|
|
||||||
if curr.value > value:
|
|
||||||
curr = curr.left
|
|
||||||
elif curr.value < value:
|
|
||||||
curr = curr.right
|
|
||||||
else:
|
|
||||||
curr = self.__delete(prev, curr)
|
|
||||||
|
|
||||||
def __iter__(self) -> Iterator[T]:
|
|
||||||
yield from traverse(self.__root)
|
def remove[T](node: BinarySearchTree[T], value: T) -> BinarySearchTree[T]:
|
||||||
|
if node is None:
|
||||||
|
return node
|
||||||
|
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
|
||||||
|
@ -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(iter(bst)) == sorted(filter(lambda x: x not in fil, nums))
|
assert list(traverse(bst)) == sorted(filter(lambda x: x not in NUMS_FILTER, 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))
|
Reference in New Issue
Block a user