k-d strom je statická binární stromová datová struktura, která se používá na vyhledávání v multidimenzionálním prostoru (porovnává více kritérií) - podobně jako range tree
[!note] Pozor
- tato stromová struktura není samovyvažovací (i když existují samovyvažovací verze adaptive k-d trees)
- často se s ní pracuje tak, že pracujeme nad statickými daty
“k” ve názvu k-d trees odkazuje na počet dimenzí (vlastností), se kterými pracujeme.
Takže kořen začne s výběrem jedné z dimenzí (dejme tomu dimenze $x$). Děti tohoto vrcholu budou naopak porovnávat podle dimenze $y$. Takto se alternuje mezi $k$ (v našem případě 2 dimenzemi).
Vizuálně se nad tím dá uvažovat tak, že kořen rozděluje náš k-dimenzionální prostor na dvě půlky v dimenzi $x$. Jeho děti pak rozdělují již přidělenou půlku v dimenzi $y$.

Jelikož se počet bodů snižuje o polovinu v každé hladině, platí že výška stromu je $O(\log n)$, kde $n$ je celkový počet bodů
Pokud pracujeme se statickými daty, můžeme sestavit perfektně vybalancovaný strom, což zaručuje optimální výkon při vyhledávání.
Konstrukce probíhá rekurzivně metodou rozděl a panuj:
Nejužitečnější operace je operace nalezení nejbližšího souseda.
Cílem je najít bod ve stromě, který je nejblíže zadanému bodu $Q$ (query point).
Při návratu nahoru po stromě (unwinding) v každém uzlu kontrolujeme:
Cílem je najít všechny body, které leží uvnitř zadaného hyper-boxu (ve 2D případě se jedná o obdelník).
Princip: Algoritmus prochází strom a porovnává dotazovaný rozsah s rozsahem (obdélníkem), který reprezentuje aktuální uzel.
Složitost závisí na počtu dimenzí $k$:
[!important] “curse of dimensionality” Ze vzorce $O(n^{1−1/k}+m)$, s rostoucím počtem dimenzí $k$ se exponent blíží k $1$. To znamená, že ve vysokých dimenzích (např. $100D$) se k-d strom začíná chovat skoro jako lineární vyhledávání $O(n)$ a ztrácí svou výhodu.
Představ si, že tvůj vyhledávací obdélník je velmi úzký (vypadá jako čára). Chceme spočítat, kolik oblastí (uzlů) taková čára může protnout.
V 2D k-d stromě se dělení střídá: $x,y,x,y…$
Klasický strom (úplné prohledání): Kdybychom v každém kroku navštívili oba syny (všechny podstromy), počet navštívených uzlů by se v každé hladině zdvojnásobil. V hloubce $h$ bychom měli $2h$ uzlů. Jelikož výška stromu je $h=\log_2n$, celkový počet uzlů je $2^{\log_2 n}=n$. (To je lineární průchod).
Náš případ (k-d strom): My ale nenavštěvujeme oba syny v každém kroku. Děláme to jen v každém druhém kroku (jen když řežeme podle osy $x$).
Výsledek: Efektivně se “rozvětvujeme” (násobíme počet uzlů dvěma) jen v polovině případů oproti plnému stromu.
Pokud má strom výšku $h$, my se rozvětvíme jen $\frac{h}{2}$-krát. Počet navštívených uzlů tedy není $2^h$, ale: \(2^{h/2}\) A teď dosadíme za $h$ (výška stromu je $\log_2 n$): \(2^{\frac{log_2 n}{2}} = (2^{\log_2 n})^{1/2} = n^{1/2} = \sqrt n\) —
Standardní k-d strom je skvělý pro statická data (postavíš ho jednou a pak jen hledáš). Pokud do něj ale začneš nekontrolovaně vkládat body, strom se „zkroutí“ a přestane být vyvážený. Tady nastupují BB(alpha) tree (weight balanced tree) (Bounded Balance stromy, známé také jako stromy s váhovou vyvážeností).
Místo toho, aby byl k-d strom vyvažován rotacemi, použije se technika částečného přestavění (partial rebuilding).