Haskell Hero
Interaktivní učebnice pro začínající Haskellisty
|
|
Sázíme stromyO binárních stromech![]() Binární strom Binární strom je datová struktura. Může být buďto prázdný nebo neprázdný. Neprázdný strom se skládá z
V Haskellu jej budeme definovat následovně: data BinTree a = Empty | Node a (BinTree a) (BinTree a)kde Empty označuje prázdný strom. Neprázdný strom je definován jako
Node a (BinTree a) (BinTree a)kde ve výrazu Node x l r označuje x hodnotu v kořeni, l levý podstrom a r pravý podstrom.
![]() Ukázky binárních stromů typu BinTree Int
Funkce na binárních stromechPříklad
Definujte funkci Jak začít? Drtivá většina funkcí na binárních stromech vypadá následovně:
Můžeme si tedy nadepsat definici: size :: BinTree a -> Int size Empty = size (Node x l r) = Kolik uzlů je v prázdném stromě? Přesně nula. Můžeme tedy doplnit první klauzuli. size Empty = 0 Kolik uzlů je v neprázdném stromě? Na tuto otázku už není možné odpovědět tak rychle, jako na předchozí. Podívejme se, co máme k dispozici. Je to hodnota v kořeni, levý podstrom a pravý podstrom. Nic víc.
Kolik je uzlů v takovém stromě? Přesně tolik, kolik je dohromady v levém podstromu, v pravém podstromu a v kořeni. Čili rekurzivně spočítáme uzly v levém podstromu, spočítáme uzly v pravém podstromu a přičteme jedničku za uzel v kořeni. A přesně tak to zapíšeme. size (Node x l r) = size l + size r + 1Vidíme, že nám nezáleží na hodnotě v kořeni, takže můžeme x nahradit podtržítkem. Celá definice tedy vypadá následovně:
size :: BinTree a -> Int size Empty = 0 size (Node _ l r) = size l + size r + 1 Vzorové vyhodnoceníUkážeme si, jak vypadá počítání uzlů tříuzlového stromu.
size (Node 5 -- x
(Node 2 Empty Empty) -- l
(Node 4 Empty Empty) -- r
)
~> size (Node 2 Empty Empty) + size (Node 4 Empty Empty) + 1
~> size Empty + size Empty + 1 + size (Node 4 Empty Empty) + 1
~> 0 + size Empty + 1 + size (Node 4 Empty Empty) + 1
~> 0 + 0 + 1 + size (Node 4 Empty Empty) + 1
~> 0 + 0 + 1 + size Empty + size Empty + 1 + 1
~> 0 + 0 + 1 + 0 + size Empty + 1 + 1
~> 0 + 0 + 1 + 0 + 0 + 1 + 1
~>* 3
n-ární stromyKromě binárních stromů můžeme definovat i stromy n-ární. Od binárních stromů se liší tím, že každý uzel může mít libovolný počet následníků. Tvar n-árního stromu má například běžná adresářová struktura. ![]() Ukázka n-árního stromu typu NTree Char
V Haskellu budeme n-ární stromy definovat následovně: data NTree a = Nnode a [ NTree a ]kde ve výrazu Nnode x s je x hodnota uzlu a s seznam následníků.
![]() Příklady n-árních stromů Všimněme si, že nemáme definován prázdný strom. Pokud bychom jej měli, tento zápis by vedl k nejednoznačnosti zápisu jednotlivých stromů. Například jednouzlový strom by mohl být definován následně: data NTree a = Empty | Nnode a [ NTree a ] Nnode 3 [] Nnode 3 [Empty] Nnode 3 [Empty, Empty] Nnode 3 [Empty, Empty, Empty] Nnode 3 [Empty, Empty, Empty, Empty] ... funkce na n-árních stromechPříklad
Definujte funkci Když se podíváme, jak n-ární strom vypadá, logicky nám vyplyne následující postup:
K rekurzivnímu sečtení všech stromů v seznamu podstromů použijeme funkci treeSum :: NTree Integer -> Integer treeSum (Nnode x s) = sum (map treeSum s) + x Vzorové vyhodnocení
treeSum (Nnode 5 [
Nnode 4 [],
Nnode 6 [],
Nnode 8 []
])
~> sum (map treeSum [ Nnode 4 [], Nnode 6 [], Nnode 8 [] ]) + 5
~>* sum [ 4 , 6 , 8 ] + 5
~>* 18 + 5
~> 23
|



