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

Myšlenka

“k” ve názvu k-d trees odkazuje na počet dimenzí (vlastností), se kterými pracujeme.

Ukázka principu (na dvou dimenzích $x$, $y$)

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$.

Image

Charakteristické vlastnosti

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ů

Operace

Build

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:

  1. Výběr osy: Zvolíme dimenzi (osu), podle které budeme prostor dělit. Dimenze se v každém patře stromu pravidelně střídají (např. $x→y→z→x→\dots$).
  2. Hledání mediánu: V aktuální sadě bodů najdeme medián vzhledem ke zvolené ose.
  3. Vytvoření uzlu: Tento medián se stane kořenem (dělicím bodem). Body s menší hodnotou v dané ose jdou do levého podstromu, body s větší hodnotou do pravého.
  4. Rekurze: Proces opakujeme pro levou a pravou část s nově zvolenou osou, dokud nerozdělíme všechny body.

Analýza složitosti

Nearest neighbor

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).

1. Průchod dolů (hledání kandidáta)

2. Průchod nahoru (rekurze a prořezávání)

Při návratu nahoru po stromě (unwinding) v každém uzlu kontrolujeme:

  1. Je uzel blíž? Pokud je uzel, kterým se vracíme, blíže k $Q$ než náš “current best”, aktualizujeme “current best”.
  2. Mám jít do druhé větve? Musíme zjistit, zda v podstromě, který jsme původně přeskočili, může být bližší bod.

Tipy pro efektivitu

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.

Časová složitost

Složitost závisí na počtu dimenzí $k$:

  1. Pro $k=2$ (2D strom): Složitost je $O(\sqrt{n})$.
  2. Pro obecné k: Složitost je $O(n^{1−1/k}+m)$.

[!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.

Vysvětlení časové složitosti

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…$

Intuitivní vysvětlení

  1. 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_2​n$, celkový počet uzlů je $2^{\log_2 ​n}=n$. (To je lineární průchod).

  2. 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\) —

Dynamické k-d stromy

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).