AVL-träd
AVL-träd | |||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Typ | Träd | ||||||||||||||||||||||||||||
Uppfunnet | 1962 | ||||||||||||||||||||||||||||
Uppfunnet av | Georgy Adelson-Velsky och Evgenii Landis | ||||||||||||||||||||||||||||
Komplexiteter i stor O-notation | |||||||||||||||||||||||||||||
|
Inom datavetenskap är ett AVL-träd (uppkallat efter uppfinnarna A delson -V elsky och L andis) ett självbalanserande binärt sökträd . Det var den första sådan datastruktur som uppfanns. I ett AVL-träd skiljer sig höjderna av de två underordnade underträden av någon nod med högst en; om de vid något tillfälle skiljer sig med mer än en, görs ombalansering för att återställa denna egenskap. Uppslagning, infogning och radering tar alla O (log n ) tid i både genomsnittliga och värsta fall, där är antalet noder i trädet före operationen. Infogningar och borttagningar kan kräva att trädet balanseras om av en eller flera trädrotationer .
AVL-trädet är uppkallat efter dess två sovjetiska uppfinnare, Georgy Adelson-Velsky och Evgenii Landis , som publicerade det i sin tidning från 1962 "An algorithm for the organisation of information".
AVL-träd jämförs ofta med röd-svarta träd eftersom båda stöder samma uppsättning operationer och tar tid för de grundläggande operationerna. För uppslagsintensiva tillämpningar är AVL-träd snabbare än rödsvarta träd eftersom de är mer strikt balanserade. I likhet med röd-svarta träd är AVL-träd höjdbalanserade. Båda är i allmänhet varken viktbalanserade eller -balanserade för någon ; det vill säga syskonnoder kan ha enormt olika antal ättlingar.
Definition
Balansfaktor
I ett binärt träd definieras balansfaktorn för en nod X som höjdskillnaden
av dess två underträd. Ett binärt träd definieras som ett AVL-träd om det är invariant
gäller för varje nod X i trädet.
En nod X med kallas "vänstertung", en med kallas "höger-tung", och en med kallas ibland helt enkelt "balanserad".
Egenskaper
Balansfaktorer kan hållas uppdaterade genom att känna till tidigare balansfaktorer och höjdförändringen – det är inte nödvändigt att veta den absoluta höjden. För att hålla AVL-balansinformationen räcker två bitar per nod.
Höjden (räknas som det maximala antalet nivåer) för ett AVL-träd med -noder ligger i intervallet:
där är det gyllene snittet och höjden innehåller minst noder där är Fibonacci-sekvensen med frövärdena
Operationer
Skrivskyddade operationer för ett AVL-träd innebär att utföra samma åtgärder som skulle utföras på ett obalanserat binärt sökträd, men modifieringar måste observera och återställa höjdbalansen för underträden.
Sökande
Att söka efter en specifik nyckel i ett AVL-träd kan göras på samma sätt som för alla balanserade eller obalanserade binära sökträd . För att sökningen ska fungera effektivt måste den använda en jämförelsefunktion som upprättar en total ordning (eller åtminstone en total förbeställning ) på uppsättningen nycklar. Antalet jämförelser som krävs för framgångsrik sökning begränsas av höjden h och för misslyckad sökning är mycket nära h , så båda är i O(log n ) .
Traversering
Som en skrivskyddad operation fungerar genomgången av ett AVL-träd på samma sätt som på vilket annat binärt träd som helst. Att utforska alla n noder i trädet besöker varje länk exakt två gånger: ett nedåtgående besök för att gå in i underträdet som är rotat av den noden, ett annat besök uppåt för att lämna den nodens underträd efter att ha utforskat det.
När en nod har hittats i ett AVL-träd, kan nästa eller föregående nod nås i avskriven konstant tid. Vissa tillfällen av att utforska dessa "nära" noder kräver att man korsar upp till h ∝ log( n ) länkar (särskilt när man navigerar från bladet längst till höger i rotens vänstra underträd till roten eller från roten till bladet längst till vänster i rotens högra underträd; i AVL-trädet i figur 1 tar navigeringen från nod P till noden Q näst till höger 3 steg). Eftersom det finns n −1 länkar i vilket träd som helst, är den amorterade kostnaden 2×( n −1)/ n , eller ungefär 2.
Föra in
När du infogar en nod i ett AVL-träd följer du till en början samma process som att infoga i ett binärt sökträd . Om trädet är tomt, infogas noden som trädets rot. Om trädet inte är tomt, går vi ner i roten och går rekursivt ner i trädet och söker efter platsen för att infoga den nya noden. Denna genomgång styrs av jämförelsefunktionen. I det här fallet ersätter noden alltid en NULL-referens (vänster eller höger) för en extern nod i trädet, dvs noden görs antingen till vänster- eller höger-underordnad till den externa noden.
Efter denna infogning, om ett träd blir obalanserat, är endast förfäder till den nyligen infogade noden obalanserade. Detta beror på att endast dessa noder har sina underträd ändrade. Så det är nödvändigt att kontrollera var och en av nodens förfäder för överensstämmelse med AVL-trädens invarianter: detta kallas "retracing". Detta uppnås genom att beakta balansfaktorn för varje nod.
Eftersom höjden på ett AVL-underträd med en enstaka infogning inte kan öka med mer än en, kommer den temporära balansfaktorn för en nod efter en insättning att ligga i intervallet [ –2,+2]. För varje kontrollerad nod, om den temporära balansfaktorn förblir i intervallet från –1 till +1 är endast en uppdatering av balansfaktorn och ingen rotation nödvändig. Men om den temporära balansfaktorn är ±2, är underträdet som är rotat vid denna nod AVL-obalanserat, och en rotation behövs. Med insättning som koden nedan visar, balanserar den adekvata rotationen omedelbart trädet perfekt.
I figur 1, genom att infoga den nya noden Z som ett barn till nod X, ökar höjden på det underträdet Z från 0 till 1.
- Invariant av retracing-slingan för en infogning
Höjden på underträdet som är rotat av Z har ökat med 1. Det är redan i AVL-form.
Exempelkod för en infogningsoperation
|
---|
För att uppdatera balansfaktorerna för alla noder, observera först att alla noder som kräver korrigering ligger från barn till förälder längs vägen för det infogade bladet. Om ovanstående procedur tillämpas på noder längs denna väg, med början från bladet, kommer varje nod i trädet åter att ha en balansfaktor på -1, 0 eller 1.
Återgången kan stoppas om balansfaktorn blir 0, vilket innebär att höjden på det underträdet förblir oförändrad.
Om balansfaktorn blir ±1 så ökar höjden på underträdet med ett och återgången måste fortsätta.
Om balansfaktorn tillfälligt blir ±2 måste detta repareras genom en lämplig rotation varefter underträdet har samma höjd som tidigare (och dess rot balansfaktorn 0).
Tiden som krävs är O(log n ) för uppslagning, plus maximalt O(log n ) spårningsnivåer ( O(1) i genomsnitt) på vägen tillbaka till roten, så operationen kan slutföras i O(log n ) tid.
Radera
De preliminära stegen för att ta bort en nod beskrivs i avsnittet Binärt sökträd#Deletion . Där minskar den effektiva raderingen av ämnesnoden eller ersättningsnoden höjden på motsvarande barnträd antingen från 1 till 0 eller från 2 till 1, om den noden hade ett barn.
Med början vid detta underträd är det nödvändigt att kontrollera var och en av förfäderna för överensstämmelse med AVL-trädens invarianter. Detta kallas "retracing".
Eftersom höjden på ett AVL-underträd med en enstaka radering inte kan minska med mer än en, kommer den temporära balansfaktorn för en nod att ligga i intervallet från -2 till +2. Om balansfaktorn förblir i området från −1 till +1 kan den justeras i enlighet med AVL-reglerna. Om det blir ±2 är underträdet obalanserat och måste roteras. (Till skillnad från insättning där en rotation alltid balanserar trädet, efter radering, kan det finnas BF(Z) ≠ 0 (se figur 2 och 3), så att efter lämplig enkel- eller dubbelrotation minskar höjden på det ombalanserade underträdet med en betydelse att trädet måste balanseras om igen på nästa högre nivå.) De olika fallen av rotationer beskrivs i avsnittet Ombalansering .
- Invariant av spårningsslingan för en radering
Höjden på underträdet som är rotat av N har minskat med 1. Det är redan i AVL-form.
Exempelkod för en raderingsoperation
|
---|
Återgången kan stoppas om balansfaktorn blir ±1 (den måste ha varit 0) vilket betyder att höjden på det underträdet förblir oförändrad.
Om balansfaktorn blir 0 (den måste ha varit ±1) så minskar höjden på underträdet med ett och spårningen måste fortsätta.
Om balansfaktorn tillfälligt blir ±2 måste detta repareras med en lämplig rotation. Det beror på balansfaktorn för syskonen Z (det högre barnträdet i figur 2) om höjden på underträdet minskar med en – och spårningen behöver fortsätta – eller inte ändras (om Z har balansfaktorn 0) och hela trädet är i AVL-form.
Tiden som krävs är O(log n ) för uppslagning, plus maximalt O(log n ) spårningsnivåer ( O(1) i genomsnitt) på vägen tillbaka till roten, så operationen kan slutföras i O(log n ) tid.
Set operationer och bulk operationer
Utöver operationerna för insättning, radering och uppslagning av ett element med ett element har flera uppsättningsoperationer definierats på AVL-träd: union , intersection och set difference . Sedan kan snabba bulkoperationer på infogningar eller borttagningar implementeras baserat på dessa inställda funktioner. Dessa uppsättningsoperationer är beroende av två hjälpoperationer, Split och Join . Med den nya verksamheten kan implementeringen av AVL-träd bli mer effektiv och mycket parallelliserbar.
Funktionen Sammanfoga på två AVL-träd t 1 och t 2 och en nyckel k kommer att returnera ett träd som innehåller alla element i t 1 , t 2 samt k . Det kräver k är större än alla nycklar i t 1 och mindre än alla nycklar i t 2 . Om de två träden skiljer sig åt i höjd med högst en, enkelt en ny nod med vänster underträd t 1 , rot k och höger underträd t 2 . Anta annars att t 1 är högre än t 2 för mer än en (det andra fallet är symmetriskt). Join följer den högra ryggraden på t 1 tills en nod c som är balanserad med t 2 . Vid denna tidpunkt skapas en ny nod med vänster underordnad c , rot k och höger underordnat t 2 för att ersätta c. Den nya noden uppfyller AVL-invarianten, och dess höjd är en större än c . Ökningen i höjd kan öka höjden på dess förfäder, vilket möjligen ogiltigförklarar AVL-invarianten för dessa noder. Detta kan fixas antingen med en dubbelrotation om den är ogiltig hos föräldern eller en enkel vänsterrotation om den är ogiltig högre i trädet, i båda fallen återställer höjden för eventuella ytterligare förfädernoder. Anslutning kommer därför att kräva högst två rotationer. Kostnaden för denna funktion är skillnaden mellan höjderna mellan de två ingångsträden.
Pseudokodimplementering för Join-algoritmen
|
---|
funktion JoinRightAVL(TL , k, TR ) (l, k', c) = exponera(TL ) if ( Höjd (c) <= Höjd( TR )+1) T' = Nod(c, k, T R ) if (Height(T') <= Height(l)+1) then return Node(l, k', T') else return rotateLeft(Node(l, k', rotateRight(T'))) else T' = JoinRightAVL(c, k, TR ) T'' = Nod(l, k', T') if (Height(T') <= Height(l)+1) return T'' annars return rotateLeft( T'') funktion JoinLeftAVL(TL , k, TR ) /* symmetrisk till JoinRightAVL */ function Join( TL , k, TR ) if (Höjd( TL )>Höjd(TR ) +1) returnerar JoinRightAVL(TL , k, TR ) if (Höjd(TR ) >Höjd( TL )+1) returnera JoinLeftAVL(TL , k, TR ) return Node( TL , k, TR ) Här är Height(v) höjden på ett underträd (nod) v . (l,k,r) = expose(v) extraherar v :s vänstra underordnade l , nyckeln k för v :s rot, och det högra barnet r . Node(l,k,r) betyder att skapa en nod av vänster underordnat l , nyckel k , och höger underordnat r . |
För att dela upp ett AVL-träd i två mindre träd, de som är mindre än tangenten k , och de som är större än tangenten k , ritar du först en bana från roten genom att infoga k i AVL:n. Efter denna infogning kommer alla värden mindre än k att hittas till vänster om banan, och alla värden större än k kommer att hittas till höger. Genom att använda Join slås alla underträd på vänster sida samman nedifrån och upp med hjälp av tangenter på banan som mellannoder från botten till toppen för att bilda det vänstra trädet, och den högra delen är asymmetrisk. Kostnaden för Split är O(log n ) , ordning efter trädets höjd.
Pseudokodimplementering för Split-algoritmfunktionen
|
---|
Split (T, k) if (T = noll) return (noll, falsk, noll) (L,m,R) = exponera(T) om (k = m) return (L, sant , R) if (k<m) (L',b,R') = Split(L,k) return (L', b, Join(R', m, R)) if (k>m) (L ',b,R') = Split(R, k) return (Gå med(L, m, L'), b, R')) |
Unionen av två AVL-träd t 1 och t 2 som representerar mängderna A och B , är en AVL t som representerar A ∪ B .
Pseudokodimplementering för unionens algoritm
|
---|
funktion Union(t 1 , t 2 ): om t 1 = noll: returnera t 2 om t 2 = noll: returnera t 1 (t < , b, t > ) = Split(t 2 , t 1 .root) returnera Gå med (Union(vänster(t 1 ), t < ), t 1 .root, Union(höger(t 1 ), t > )) Här antas Split returnera två träd: ett som håller tangenterna minus dess inmatningsnyckel, ett som håller de större tangenterna. (Algoritmen är oförstörande , men det finns en destruktiv version på plats också.) |
Algoritmen för korsning eller skillnad är liknande, men kräver Join2- hjälparrutinen som är samma som Join men utan mitttangenten. Baserat på de nya funktionerna för union, korsning eller differens kan antingen en nyckel eller flera nycklar infogas i eller raderas från AVL-trädet. Eftersom Split anropar Join men inte hanterar balanseringskriterierna för AVL-träd direkt, brukar en sådan implementering kallas den "join-baserade" implementeringen .
Komplexiteten för var och en av union, skärningspunkt och skillnad är för AVL-träd i storlekarna och . Ännu viktigare, eftersom de rekursiva anropen till union, korsning eller skillnad är oberoende av varandra, kan de utföras parallellt med ett parallellt djup . När har den kopplingsbaserade implementeringen samma beräknings-DAG som insättning och borttagning av enstaka element.
Återbalansering
Om höjdskillnaden mellan två underträd under en modifieringsoperation ändras, kan detta, så länge den är < 2, reflekteras av en anpassning av balansinformationen hos föräldern. Under infogning och borttagning kan en (tillfällig) höjdskillnad på 2 uppstå, vilket innebär att det överordnade underträdet måste "ombalanseras". De givna reparationsverktygen är de så kallade trädrotationerna , eftersom de flyttar nycklarna endast "vertikalt", så att den ("horisontella") sekvensen av nycklarna i sin ordning bevaras helt (vilket är väsentligt för ett binärt sökträd ).
Låt X vara den nod som har en (tillfällig) balansfaktor på −2 eller +2. Dess vänstra eller högra underträd modifierades. Låt Z vara det högre barnet (se figur 2 och 3). Observera att båda barnen är i AVL-form genom induktionshypotes .
Vid insättning har denna insättning hänt ett av Z:s barn på ett sätt att Z:s längd har ökat. Vid radering har denna radering hänt syskonen t 1 till Z på ett sätt så att t 1 :s höjd som redan är lägre har minskat. (Detta är det enda fallet där Z:s balansfaktor också kan vara 0.)
Det finns fyra möjliga varianter av överträdelsen:
Eller hur | ⟹ Z är en rättighet | barn till sin förälder X och BF(Z) ≥ 0 | |
Vänster Vänster | ⟹ Z är en vänster | barn till dess förälder X och BF(Z) ≤ 0 | |
Höger vänster | ⟹ Z är en rättighet | barn till dess förälder X och BF(Z) < 0 | |
Vänster höger | ⟹ Z är en vänster | barn till dess förälder X och BF(Z) > 0 |
Och ombalanseringen utförs annorlunda:
Eller hur | ⟹ X balanseras om med a | enkel | rotation rotate_Left
|
(se figur 2) | |
Vänster Vänster | ⟹ X balanseras om med a | enkel | rotation rotate_Right
|
(spegelbild av figur 2) | |
Höger vänster | ⟹ X balanseras om med a | dubbel | rotation rotate_RightLeft
|
(se figur 3) | |
Vänster höger | ⟹ X balanseras om med a | dubbel | rotation rotate_LeftRight
|
(spegelbild av figur 3) |
Därmed betecknas situationerna som CB , där C (= barnriktning) och B (= balans) kommer från mängden { Vänster , Höger } med Höger := − Vänster . Balansbrottet i fallet C == B repareras med en enkel rotation rotate_
(− C ), medan fallet C != B repareras med en dubbelrotation rotate_
CB .
Kostnaden för en rotation, antingen enkel eller dubbel, är konstant.
Enkel rotation
Figur 2 visar en Right Right-situation. I sin övre halva har nod X två barnträd med en balansfaktor på +2 . Dessutom är det inre barnet t23 av Z (dvs vänster barn när Z är höger barn, eller höger barn när Z är vänster barn) inte högre än sitt syskon t4 . Detta kan ske genom en höjdökning av underträdet t 4 eller genom en höjdminskning av underträdet t 1 . I det senare fallet kan även den bleka situationen där t 23 har samma höjd som t 4 förekomma.
Resultatet av vänsterrotationen visas i den nedre halvan av figuren. Tre länkar (tjocka kanter i figur 2) och två balansfaktorer ska uppdateras.
Som figuren visar låg bladskiktet före en insättning på nivå h+1, tillfälligt på nivå h+2 och efter rotationen igen på nivå h+1. Vid en deletion var bladskiktet på nivå h+2, där det återigen är, när t 23 och t 4 var av samma höjd. Annars når lövskiktet nivå h+1, så att höjden på det roterade trädet minskar.
- Kodavsnitt för en enkel vänsterrotation
Inmatning: | X = roten till underträdet som ska roteras åt vänster |
Z = höger underordnad av X, Z är höger-tung | |
med höjd == Höjd(VänsterSubträd( X ))+2 | |
Resultat: | ny rot av ombalanserat underträd |
Dubbel rotation
Figur 3 visar en höger vänster-situation. I sin övre tredjedel har nod X två barnträd med en balansfaktor på +2 . Men till skillnad från figur 2 är det inre barnet Y till Z högre än sitt syskon t 4 . Detta kan ske genom införandet av Y själv eller en höjdökning av ett av dess underträd t 2 eller t 3 (med konsekvensen att de har olika höjd) eller genom en höjdminskning av underträdet t 1 . I det senare fallet kan det också förekomma att t 2 och t 3 är av samma höjd.
Resultatet av den första, den högra, rotationen visas i den mellersta tredjedelen av figuren. (Med avseende på balansfaktorerna är denna rotation inte av samma slag som de andra AVL enkelrotationerna, eftersom höjdskillnaden mellan Y och t 4 bara är 1.) Resultatet av den sista vänsterrotationen visas i den nedre tredjedelen av figuren. Fem länkar (tjocka kanter i figur 3) och tre balansfaktorer ska uppdateras.
Som figuren visar låg bladskiktet före en insättning på nivå h+1, tillfälligt på nivå h+2 och efter dubbelrotationen igen på nivå h+1. Vid en deletion låg bladlagret på nivå h+2 och efter dubbelrotationen är det på nivå h+1, så att höjden på det roterade trädet minskar.
- Kodavsnitt för dubbelrotation höger-vänster
Inmatning: | X = roten till underträdet som ska roteras |
Z = dess högra barn, vänstertungt | |
med höjd == Höjd(VänsterSubträd( X ))+2 | |
Resultat: | ny rot av ombalanserat underträd |
Jämförelse med andra strukturer
Både AVL-träd och röd-svarta (RB) träd är självbalanserande binära sökträd och de är matematiskt relaterade. Visserligen kan varje AVL-träd färgas röd–svart, men det finns RB-träd som inte är AVL-balanserade. För att bibehålla AVL (eller RB-trädets invarianter) spelar rotationer en viktig roll. I värsta fall, även utan rotationer, kräver AVL- eller RB-insättningar eller -raderingar O(log n ) -inspektioner och/eller uppdateringar av AVL-balansfaktorer (eller RB-färger). RB-insättningar och -deletioner och AVL-insättningar kräver från noll till tre svansrekursiva rotationer och körs i amorterad O(1) -tid, alltså lika konstant i genomsnitt. AVL-deletioner som kräver O(log n ) -rotationer i värsta fall är också O(1) i genomsnitt. RB-träd kräver att man lagrar en bit information (färgen) i varje nod, medan AVL-träd oftast använder två bitar för balansfaktorn, även om det räcker med en bit med betydelsen "lägre än syskon" när de lagras hos barnen. Den större skillnaden mellan de två datastrukturerna är deras höjdgräns.
För ett träd av storlek n ≥ 1
- ett AVL-träds höjd är högst
- φ det gyllene snittet , och .
- ett RB-träds höjd är högst
- .
AVL-träd är mer styvt balanserade än RB-träd med en asymptotisk relation AVL/RB ≈0,720 av de maximala höjderna. För insättningar och deletioner visar Ben Pfaff i 79 mätningar en relation mellan AVL/RB mellan 0,677 och 1,077 med median ≈0,947 och geometriskt medelvärde ≈0,910.
Se även
-
^ a b c d e f
Eric Alexander. "AVL-träd" . Arkiverad från originalet den 31 juli 2019.
{{ citera webben }}
: CS1 underhåll: unfit URL ( länk ) - ^ Sedgewick, Robert (1983). "Balanserade träd" . Algoritmer . Addison-Wesley. sid. 199 . ISBN 0-201-06672-6 .
- ^ Adelson-Velsky, Georgy; Landis, Evgenii (1962). "En algoritm för organisation av information". Proceedings of the USSR Academy of Sciences (på ryska). 146 : 263–266. Engelsk översättning av Myron J. Ricci i Soviet Mathematics - Doklady , 3:1259–1263, 1962.
- ^ a b Pfaff, Ben (juni 2004). "Prestandaanalys av BST:er i systemprogramvara" (PDF) . Stanford University .
-
^
AVL-träd är inte viktbalanserade? (vilket betyder: AVL-träd är inte μ-balanserade?) Därmed: Ett binärt träd kallas -balanserat, med , om för varje nod , olikheten - ^ a b c d Knuth, Donald E. (2000). Sortering och sökning (2. uppl., 6. tryckning, nyuppdaterad och rev. uppl.). Boston [ua]: Addison-Wesley. ISBN 0-201-89685-0 .
- ^ Rajinikanth. "AVL Tree: Data Structures" . btechsmartclass.com . Hämtad 2018-03-09 .
- ^ Emellertid kan saldoinformationen behållas i undernoderna som en bit som indikerar om föräldern är högre med 1 eller med 2; därigenom kan högre med 2 inte förekomma för båda barnen. På detta sätt är AVL-trädet ett "rank balanserat" träd , som myntats av Haeupler, Sen och Tarjan .
- ^ Dixit, JB (2010). Bemästra datastrukturer genom "C"-språket . New Delhi, Indien: University Science Press, ett avtryck av Laxmi Publications Pvt. Ltd. ISBN 9789380386720 . OCLC 939446542 .
- ^ a b c Brass, Peter (2008). Avancerade datastrukturer . Cambridge: Cambridge University Press. ISBN 9780511438202 . OCLC 312435417 .
- ^ Hubbard, John Rast (2000). Schaums översikt över teori och problem med datastrukturer med Java . New York: McGraw-Hill. ISBN 0071378707 . OCLC 48139308 .
- ^ a b c Pfaff, Ben (2004). En introduktion till binära sökträd och balanserade träd . Free Software Foundation, Inc.
-
^
Weiss, Mark Allen. (2006). Datastrukturer och algoritmanalys i C++ (3:e upplagan). Boston: Pearson Addison-Wesley. sid. 145. ISBN 0-321-37531-9 . OCLC 61278554 .
{{ citera bok }}
: CS1 underhåll: datum och år ( länk ) - ^ a b Blelloch, Guy E.; Ferizovic, Daniel; Sun, Yihan (2016), "Just join for parallel ordered sets", Symposium on Parallel Algorithms and Architectures , ACM, s. 253–264, arXiv : 1602.02120 , doi : 10.1145/2935764-409 35764-409 35764-409 35764-409 35764-409 35764-409 453-264 . 10- 0 , S2CID 2897793 .
- ^ Paul E. Black (2015-04-13). "AVL-träd" . Ordbok över algoritmer och datastrukturer . National Institute of Standards and Technology . Hämtad 2016-07-02 .
- ^ Kurt Mehlhorn , Peter Sanders : "Algorithmer och datastrukturer. Den grundläggande verktygslådan." Springer, Berlin/Heidelberg 2008, ISBN 978-3-540-77977-3 , doi : 10.1007/978-3-540-77978-0 .
- ^ Dinesh P. Mehta, Sartaj Sahni (Ed.) Handbok för datastrukturer och tillämpningar 10.4.2
- ^ Rött–svart träd#Proof of bounds
Vidare läsning
- Donald Knuth . The Art of Computer Programming , Volym 3: Sortering och sökning , tredje upplagan. Addison-Wesley, 1997. ISBN 0-201-89685-0 . Sidorna 458–475 i avsnitt 6.2.3: Balanserade träd.
- Haeupler, Bernhard; Sen, Siddhartha; Tarjan, Robert E. (2015), "Rank-balanced trees" (PDF) , ACM Transactions on Algorithms , 11 (4): Art. 30, 26, doi : 10.1145/2689412 , MR 3361215 , S2CID 1407290 .
externa länkar
- Den här artikeln innehåller material som är allmän egendom från Paul E. Black. "AVL-träd" . Ordbok över algoritmer och datastrukturer . NIST .