87 lines
2.3 KiB
Markdown
87 lines
2.3 KiB
Markdown
# Rekursive Datenstrukturen
|
|
|
|
|
|
## [LinkedList](./lists.py)
|
|
|
|
In der Vorlesung wurden uns rekursive Datenstrukturen vorgestellt. Und zwar in der einfachsten Form, einer Liste. Hierbei modellieren wir eine *Node* Datenstruktur die unseren Wert *Value* trägt und auf die nächste *Node* in der Liste verweist durch *next_node*.
|
|
|
|
```python
|
|
from dataclasses import dataclass
|
|
from typing import Optional
|
|
|
|
@dataclass
|
|
class Node[T]:
|
|
value: T
|
|
next_node: Optional['Node[T]']
|
|
```
|
|
|
|
Jetzt wollen wir eine Liste um unsere Node modellieren, hierbei interessiert uns nur die erste Node *__head* und die Länge *__length*.
|
|
|
|
```python
|
|
@dataclass
|
|
class LinkedList[T]:
|
|
|
|
def __post_init__(self):
|
|
self.__head: Optional[Node[T]] = None
|
|
self.__length: int = 0
|
|
```
|
|
|
|
Jetzt geht es darum alle Standardmethoden die eine Liste braucht zu implementieren.
|
|
|
|
## [BinaryTree](./trees.py)
|
|
|
|
Jetzt wollen wir eine andere rekursive Datenstruktur definieren, den binary Tree. Diese besteht immer aus zwei Abzweigungen *right* und *left*.
|
|
|
|
```python
|
|
@dataclass
|
|
class Node[T]:
|
|
value: T
|
|
left: Optional['Node[T]']
|
|
right: Optional['Node[T]']
|
|
```
|
|
|
|
Statt jetzt eine eigene Klasse zu erstellen die `Node` intern benutzt wollen wir einfach einen Typalias erstellen und imperative mit Funktionen statt Methoden arbeiten.
|
|
|
|
```python
|
|
type BinaryTree[T] = Optional[Node[T]]
|
|
```
|
|
|
|
### `traverse`
|
|
|
|
Man kann einen BinaryTree auf drei typische arten ablaufen
|
|
|
|
- Inorder
|
|
- Erst laufen wir Links ab
|
|
- Dann schauen wir uns die Node an
|
|
- Dann laufen wir Rechts ab
|
|
- Preorder
|
|
- Erst schauen wir uns die Node an
|
|
- Dann laufen wir Links ab
|
|
- Dann laufen wir Rechts ab
|
|
- Postorder
|
|
- Erst laufen wir Links ab
|
|
- Dann laufen wir Rechts ab
|
|
- Dann schauen wir uns die Node an
|
|
|
|
Hierfür erstellen wir einen `Enum` um zu unterscheiden wie wir gerade ablaufen
|
|
|
|
```python
|
|
class TraversalType(Enum):
|
|
INORDER, POSTORDER, PREORDER = auto(), auto(), auto()
|
|
```
|
|
|
|
Und jetzt implementieren wir einen Generator der uns einen Iterator erzeugt welcher den BinaryTree in der gegebenen Order abläuft.
|
|
|
|
```python
|
|
def traverse[T](tree: BinaryTree[T], order: TraversalType = TraversalType.INORDER) -> Iterator[T]:
|
|
pass
|
|
```
|
|
|
|
Tipp:
|
|
|
|
Mit `yield from ...` kann man einen ganzen Iterator *yield*en.
|
|
|
|
```python
|
|
def my_range(start: int, end: int) -> Iterator[int]:
|
|
yield from range(start, end)
|
|
``` |