Et sammensyet binært træ er en variant af et binært træ , der tillader hurtig gennemløb - givet en pointer til en node i et sammensyet træ, kan man nemt finde den næste (og/eller forrige) node i rækkefølge .
Binære træer, inklusive (men ikke begrænset til) binære søgetræer og deres varianter, kan bruges til at gemme flere elementer i en bestemt rækkefølge. For eksempel antager et binært søgetræ, at dataelementer er ordnet på en eller anden måde og bevarer denne rækkefølge, når de indsættes og fjernes. En nyttig operation på et sådant træ er traversal , det vil sige at besøge elementerne i træet i den rækkefølge, de vil blive husket i (hvilket svarer til rækkefølgen af noderne i tilfælde af et binært søgetræ).
Den simple rekursive traversalalgoritme, der besøger hver knude i det binære søgetræ, er som følger. Antag , at t er en pointer til en knude eller nul . "Besøg" t kan betyde enhver operation med denne node t eller det indhold, der er tildelt den.
Traversal algoritme( t ):
Problemet med denne algoritme er, at algoritmen på grund af rekursion bruger stakplads proportionalt med højden af træet. Hvis træet er dårligt afbalanceret, når denne værdi O (log n ) for et træ med n elementer. I værste fald, når træet har form af en kæde , er højden af træet n , så algoritmen vil kræve O ( n ) stakplads .
I 1968 spurgte Donald Knuth , om der var en ikke-rekursiv centreret traversalalgoritme, der ikke brugte stakken og efterlod træet uændret. En løsning på dette problem er træsyning, introduceret af James H. Morris i 1979 [1] [2] .
Et syet træ er defineret som følger:
"Et binært træ sammenføjes ved at tildele alle højre underordnede pointere, som normalt ville være nul-pegere, til pointere til knudepunktets næste knude ( hvis nogen), og alle venstre underordnede pegere, som normalt ville være nul-pegere, til pointere til tidligere knudepunkter i bestilling” [3] .
Det er også muligt at finde forælderen til en node fra et sammensat binært træ uden eksplicit at bruge en markør til forælderen eller stakken, selvom det er langsommere. Dette er nyttigt, når stakken er begrænset, eller når en stak af overordnede pointere ikke er tilgængelig (til at finde en overordnet pointer ved hjælp af dybde -først-søgning ).
For at se, hvordan dette er muligt, skal du overveje en node k , der har et ret underordnet r . Så skal nodens venstre pointer r enten være et underordnet eller en pointer tilbage til k . I det tilfælde, hvor r har et venstre barn, så skal det venstre barn have sit eget venstre barn, eller en pointer tilbage til k , og så videre for alle efterfølgende venstre børn. Når vi således går gennem kæden af venstre visere fra r den ene efter den anden , finder vi til sidst stingmarkøren tilbage til k . Situationen er symmetrisk, når q er det venstre underordnede af p , i hvilket tilfælde vi kan spore de højre underordnede af knudepunktet q for at få en firmwarepointer til p .
På Python sprog :
def parent ( node ): hvis node er node . træ . root : return Ingen andre : x = node y = node mens Sand : hvis er_tråd ( y ): p = y . højre hvis p er Ingen eller p . venstre er ikke node : p = x mens det ikke er_tråd ( s . venstre ): p = p . venstre p = p . venstre retur p elif is_thread ( x ): p = x . venstre hvis p er Ingen eller p . højre er ikke node : p = y mens det ikke er_tråd ( s . højre ): p = p . højre p = p . højre retur p x = x . venstre y = y . retFirmware er links til de forrige og næste noder i en given node i henhold til en centreret gennemgang.
Hvis den syede trærækkefølge er ABCDEFGHI, kommer D-knuden før E, og F følger E-knuden.
Lad os prøve at danne et syet træ ud fra et almindeligt binært træ
Den centrerede traversale vertex-rækkefølge for træet ovenfor er DBAE C. Så det tilsvarende sammensyede binære træ ville se sådan ud
I et m-syet binært træ med n noder er der n*m - (n-1) nul-links.
Som en ikke-rekursiv gennemløbsmetode skal metoden være en iterativ procedure, alle knudegennemløbstrin skal være i en loop, så det samme kan anvendes på alle træknuder. Vi antager igen en centreret trægennemgang. Derefter krydser vi det venstre undertræ for enhver knude først (hvis det eksisterer, og hvis vi ikke har krydset det før). Vi besøger derefter (det vil sige udskriver værdien af noderne i vores tilfælde) selve noden og krydser først derefter det rigtige undertræ (hvis det findes). Hvis der ikke er noget højre træ, skal du kontrollere det syede led og gøre det syede toppunkt til den aktuelle node i betragtning. Se eksempel nedenfor.
Trin-1: For den aktuelle node skal du kontrollere, om der er et venstre barn, der ikke er på listen over besøgte. Hvis der er en, gå til trin 2, ellers gå til trin 3.
Trin-2: Sæt det venstre barn på listen over besøgte noder og gør det til den aktuelle node. Lad os gå videre til trin 6.
Trin-3: Udskriv noden, og hvis noden har et rigtigt barn, gå til trin 4, ellers gå til trin 5.
Trin-4: Gør det rigtige barn til den aktuelle node.
Trin-5: Hvis der findes en firmwarenode, skal du gøre den til den aktuelle node.
Trin-6: Hvis alle noder er udskrevet, skal du afslutte, ellers gå til trin 1.
Liste | ||||
---|---|---|---|---|
trin 1 | A har et venstre barn, dvs. B , som endnu ikke er besøgt, så vi sætter B i vores "liste over besøgte noder", og B bliver den aktuelle node. | B | ||
trin-2 | B har også et venstre barn D , som ikke er på listen over besøgte noder. Vi sætter D i besøgslisten og gør den aktuel. | BD | ||
trin-3 | Node D har ikke et venstre barn, så vi udskriver D , så tjekker vi det højre barn. D har ikke det rigtige barn, så vi kigger på det linkede link. Node har firmware til node B , så gør B aktuel. | BD | D | |
trin-4 | B har et efterladt barn, men det er allerede blevet besøgt. Så vi udskriver B , og kontrollerer derefter for et rigtigt barn, men der er ikke et, så vi gør den syede knude (dvs. A ) til den nuværende. | BD | D.B. | |
trin-5 | A har et venstre barn B , men det er allerede besøgt, så vi udskriver A og tjekker efter et højre barn. Node A har et ret underordnet C , og det er ikke på listen over besøgte noder, så vi tilføjer det til denne liste og gør det aktuelt. | bdc | DBA | |
trin-6 | C har node E som venstre underordnet, og denne node er endnu ikke blevet besøgt, så føj node E til listen og gør den aktuel. | B D C E | D B A | |
trin-7 | langt om længe….. | D B A E C |