Kd-træ

Den aktuelle version af siden er endnu ikke blevet gennemgået af erfarne bidragydere og kan afvige væsentligt fra den version , der blev gennemgået den 23. juli 2021; checks kræver 2 redigeringer .
K-dimensionelt træ
Type Multidimensionelt træ Binært søgetræ
Opfindelsens år 1975
Forfatter Jon Bentley
Kompleksitet i O-symboler
Gennemsnit I værste fald
Hukommelsesforbrug O( n ) O( n )
Søg O( logn ) O( n )
Indsæt O( logn ) O( n )
Fjernelse O( logn ) O( n )

Et k -d-træ ( eng.  kd-træ , forkortelse for k-dimensionelt træ ) er enrumopdelt datastruktur til bestilling af punkter i et k - dimensionelt rum . k -d-træer bruges til nogle applikationer, såsom flerdimensionel nøglerumssøgning (rækkeviddesøgning og nærmeste nabosøgning ). k -d-træer er en særlig slags binære søgetræer .

Matematisk beskrivelse

Et K-dimensionelt træ er et ubalanceret søgetræ til lagring af punkter fra . Det giver en R-træ- lignende evne til at søge inden for et givet nøgleområde. Til skade for forespørgslens enkelhed er hukommelseskrav i stedet for .

Der er homogene og ikke-homogene kd-træer. I homogene kd-træer gemmer hver node en post . I den heterogene variant indeholder interne noder kun nøgler, blade indeholder links til poster.

I et ikke-homogent kd-træ med et dimensionelt hyperplan parallelt med aksen i punktet . For roden skal du opdele punkterne gennem hyperplanet i to sæt punkter, der er så store som muligt og skrive til roden, til venstre for denne, alle punkter, som er gemt til, til højre, dem, for hvilke . For det venstre undertræ skal man opdele punkterne igen i et nyt "splitplan" og lagres i den interne node. Til venstre for dette, alle punkter, som . Dette fortsætter rekursivt over alle rum. Så starter alt igen fra det første rum, indtil hvert punkt tydeligt kan identificeres gennem hyperplanet.

kd træ kan indbygges . En rækkeviddesøgning kan udføres i , hvorved størrelsen af ​​svaret angives. Hukommelseskravet til selve træet er begrænset .

Operationer på k -d-træer

Struktur

Træstruktur beskrevet i C++ :

constexprint N = 10 ; _ // antal tasterum struct Item { // item structure int key [ N ]; // række af nøgler, der definerer elementet char * info ; // element information }; struct Node { // tree node structure Item i ; // element Node * venstre ; // venstre undertræ Node * højre ; // højre undertræ }

Træets struktur kan variere afhængigt af detaljerne i implementeringen af ​​algoritmen . For eksempel kan en node indeholde et array i stedet for et enkelt element, hvilket forbedrer søgeeffektiviteten.

Elementsøgningsanalyse

Det mindste antal elementer, der ses, er naturligvis , og det maksimale antal elementer, der vises, er , hvor  er højden på træet. Det er tilbage at beregne det gennemsnitlige antal sete varer .

 er det givne element.

Lad os overveje sagen . Fundne elementer kan være:

og så videre for hvert tasterum. I dette tilfælde er den gennemsnitlige søgelængde i ét rum:

.

Gennemsnitsværdien beregnes med formlen:

Det er tilbage at finde sandsynligheden . Det er lig med , hvor  er antallet af sager, hvornår og  er det samlede antal sager. Det er ikke svært at gætte hvad .

Vi erstatter dette med formlen for gennemsnitsværdien:

,

altså hvor  er træets højde.

Hvis vi går fra højden af ​​træet til antallet af elementer, så:

, hvor  er antallet af elementer i noden.

Ud fra dette kan vi konkludere, at jo flere elementer der vil være indeholdt i noden, jo hurtigere vil træsøgningen være, da højden af ​​træet forbliver minimal, men du bør ikke gemme et stort antal elementer i noden, da med denne metode kan hele træet degenerere til en normal matrix eller liste.

Tilføjelse af elementer

Tilføjelse af elementer foregår på nøjagtig samme måde som i et normalt binært søgetræ , med den eneste forskel, at hvert niveau i træet også vil blive bestemt af det rum, det tilhører.

Træprogressionsalgoritme:

for ( int i = 0 ; træ ; i ++ ) // i er mellemrumstallet if ( træ -> x [ i ] < træ -> t ) // t er mediantræet = træ - > venstre ; // flyt til venstre undertræ else træ = træ -> højre ; // flyt til højre undertræ

Tilføjelsen udføres efter , hvor  er træets højde.

Fjernelse af elementer

Når du sletter træelementer, kan der opstå flere situationer:

  • Sletning af et træblad er en ret simpel sletning, når en node slettes, og forfaderknudemarkøren simpelthen nulstilles.
  • Fjernelse af en træknude (ikke et blad) er en meget kompliceret procedure, hvor du skal genopbygge hele undertræet for denne knude.

Nogle gange løses processen med at slette en node ved at ændre kd-træet. For eksempel, hvis vores node indeholder et array af elementer, så forbliver træknuden, når hele arrayet slettes, men nye elementer er ikke længere skrevet der.

Find en række elementer

Søgningen er baseret på normal trænedstigning, hvor hver knude kontrolleres for en rækkevidde. Hvis medianerne af en knude er mindre end eller større end et givet område i et givet rum, så går gennemgangen længere langs en af ​​træets grene. Hvis medianen af ​​noden er helt inden for det givne interval, skal begge undertræer besøges.

Algoritme Z - træknude _ [( x_0_min , x_1_min , x_2_min ,..., x_n_min ),( x_0_max , x_1_max , x_2_max ,..., x_n_max )] - specificeret interval Function Array ( Node *& Z ){ Hvis ([ x_0_min , x_1_min , x_2_min ,..., x_n_min ] < Z ){ Z = Z -> venstre ; // venstre undertræ } andet Hvis ([ x_0_max , x_1_max , x_2_max ,..., x_n_max ] > Z ){ Z = Z -> højre ; // højre undertræ } Ellers { // se begge undertræer af Array ( Z -> højre ); // kør funktionen for højre undertræ Z = Z -> venstre ; // se venstre undertræ } } Analyse

Det mindste antal elementer, der ses, er naturligvis , hvor  er højden på træet. Det er også indlysende, at det maksimale antal elementer, der ses, er , dvs. at se alle elementer i træet. Det er tilbage at beregne det gennemsnitlige antal sete varer .

 - given rækkevidde.

Den originale artikel om kd-træer giver følgende karakteristika: for en fast rækkevidde.

Hvis vi går fra højden af ​​træet til antallet af elementer, så vil dette være:

Find den nærmeste nabo

Søgningen efter det nærmeste element er opdelt i to delopgaver: at bestemme det mulige nærmeste element og finde de nærmeste elementer i et givet område.

Givet et træ . Vi sænker træet til dets blade efter tilstand og bestemmer det sandsynligt nærmeste element efter tilstand . Derefter lanceres fra roden af ​​træet algoritmen til at finde det nærmeste element i det givne område, som er bestemt af radius .

Søgeradius justeres, når et tættere element er fundet.

Algoritme Z er roden af ​​træet Liste - en liste over de nærmeste fundne elementer [ x_0 , x_1 , x_2 ..., x_n ] - koordinater for alle dimensioner af vores element , for hvilke den nærmeste Len - minimum længde BØRN - det maksimale antal børn for hvert element Funktionen Maybe_Near ( Node *& Z ) { // søg efter det nærmeste mulige element, mens ( Z ) { for ( i = 0 ; i < N ; i ++ ) { // tjek elementer i node len_cur = sqrt (( x_0 - x [ i ] _0 ) ^ 2 + ( x_1 - x [ i ] _1 ) ^ 2 + . .. + ( x_n - x [ i ] _n ) ^ 2 ); // længde af nuværende element if ( Len > længde af nuværende element ) { Len = len_cur ; // sæt ny længde Slet ( Liste ); // rydde listen Tilføj ( Liste ); // tilføje et nyt element til listen } else if ( længder er ens ) { Tilføj ( Liste ); // tilføje et nyt element til listen } if (( x_0 == x [ i ] _0 ) && ( x_1 == x [ i ] _1 ) && ... && ( x_n == x [ i ] _n )) { retur 1 ; } } hvis ([ x_0 , x_1 , x_2 ..., x_n ] < Z ) Z = Z -> venstre ; // venstre undertræ hvis ([ x_0 , x_1 , x_2 ..., x_n ] > Z ) Z = Z -> højre ; // højre undertræ } } Funktion Nær ( Knudepunkt *& Z ) { // søg rekursivt efter det nærmeste element i det givne område, hvis ( ! Z ) { returnere Liste ; } len_cur = sqrt (( x_0 - x [ i ] _0 ) ^ 2 + ( x_1 - x [ i ] _1 ) ^ 2 + ... + ( x_n - x [ i ] _n ) ^ 2 ); // afstand fra vores punkt til det nuværende hvis ( len_cur < Len ) { // fandt en længde mindre end minimum Len = len_cur ; // indstilling af en ny minimumlængde Slet ( Liste ); // rydde listen - trods alt er alle elementer fundet indtil videre længere end det nuværende Tilføj ( List , Z ); // tilføje det aktuelle element til listen } else if ( len_cur == Len ) { // længden er lig med minimum Add ( List , Z ); // bare tilføje et nyt element til listen } for ( i = 0 ; i < BØRN ; i ++ ) { // gør det samme for alle børn Nær ( Z -> børn [ i ]); // se alle undertræer } } Analyse

Det mindste antal elementer, der ses, er naturligvis , hvor h er højden af ​​træet. Det er også indlysende, at det maksimale antal elementer, der ses, er , dvs. at se alle noder. Det er tilbage at beregne det gennemsnitlige antal sete varer.

 er et givet element i forhold til hvilket du vil finde det nærmeste. Denne opgave er opdelt i to underopgaver: at finde det nærmeste element i en node og at finde det nærmeste element i et givet område. For at løse det første delproblem kræves der én nedstigning langs træet, det vil sige .

For den anden delopgave, som vi allerede har beregnet, tager søgningen efter elementer i et givet område . For at finde gennemsnittet skal du blot tilføje disse to værdier:

.

Se også

Noter

Links