Binre sgetrer 1 Plan Binre sgetrer Definition Operationer
Binære søgetræer 1
Plan • Binære søgetræer Definition Operationer • Balancerede binære søgetræer AVL-træer Rød-sort-træer AA-træer • B-træer 2
Binær søgning i et sorteret array Metode: Opdel arrayet i to (næsten) lige store dele. Afgør i hvilken af de to dele, nøglen skal findes. Fortsæt søgningen i denne del på samme måde. Eksempel: Søgning efter N. A B E F G H I L M N P R S X L M N N 3
Binært søgetræ Binær søgning kan beskrives ved et binært søgetræ: I P E A M G B F H L S N R X Et binært søgetræ, er et binært træ, hvor der for hver knude X gælder, at alle knuder i dets venstre undertræ er mindre end X, og alle knuder i dets højre undertræ er større end X. 4
Binært søgetræ som abstrakt datatype public class Binary. Search. Tree implements Search. Tree { public Comparable find(Comparable x) throws Item. Not. Found; public void insert(Comparable x) throws Duplicate. Item; public void remove(Comparable x) throws Item. Not. Found; public public is. Empty(); make. Empty(); print. Tree(); Comparable find. Min(Comparable x) throws Item. Not. Found; Comparable find. Max(Comparable x) throws Item. Not. Found; Comparable remove. Min(Comparable x) throws Item. Not. Found; Comparable remove. Max(Comparable x) throws Item. Not. Found; } 5
Intern repræsentation public class Binary. Search. Tree {. . . protected Binary. Node root; } class Binary. Node { Binary. Node(Comparable e, Binary. Node lt, Binary. Node rt) { element = e; left = lt; right = rt; } Comparable element; Binary. Node left, right; } 6
Søgning public Comparable find(Comparable x) throws Item. Not. Found { return find(x, root). element; } protected Comparable find(Comparable x, Binary. Node t) throws Item. Not. Found { while (t != null) { if (x. compares(t. element) < 0) t = t. left; else if (x. compares(t. element > 0) t = t. right; else return t; } throw new Item. Not. Found("Search. Tree find"); } 7
Indsættelse 7 9 2 1 5 3 7 Indsættelse af 6 9 2 1 5 3 6 Der foretages en mislykket søgning, og den nye knude indsættes der, hvor søgningen stopper. 8
Indsættelse public void insert(Comparable x) throws Duplicate. Item { root = insert(x, root); } protected Binary. Node insert(Comparable x, Binary. Node t) throws Duplicate. Item { if (t == null) t = new Binary. Node(x, null); else if (x. compares(t. element) < 0) t = insert(x, t. left); else if (x. compares(t. element) > 0) t = insert(x, t. right); else throw new Duplicate. Item("Search. Tree insert"); return t; } 9
Sletning af roden 7 9 15 2 1 5 3 18 9 11 15 2 1 5 11 18 3 Erstat roden med den knude, der er mindst i rodens højre undertræ. Denne knuder befinder sig længst til venstre i rodens højre undertræ. Hvis det højre undertræ er tomt, fjernes roden blot fra træet. 10
Sletning public void remove(Comparable x) throws Item. Not. Found{ root = remove(x, root); } protected Binay. Node remove(Comparable x, Binary. Node t) throws Item. Not. Found { if (t == null) throw new Item. Not. Found("Search. Tree remove"); if (x. compares(t. element) < 0) t. left = remove(x, t. left); else if (x. compares(t. element) > 0) t. right = remove(t. right); else if (t. right != null) { // x found t. element = find. Min(t. right). element; t. right = remove. Min(t. right); } else t = t. left; return t; } 11
protected Binary. Node find. Min(Binary. Node t) throws Item. Not. Found { if (t == null) throw new Item. Not. Found("Search. Tree find. Min"); while (t. left != null) t = t. left; return t; } protected Binary. Node remove. Min(Binary. Node t) throws Item. Not. Found { if (t == null) throw new Item. Not. Found("Search. Tree remove. Min"); if (t. left == null) return t. right; t. left = remove. Min(t. left); return t; } 12
Alternativ implementering af sletning Binary. Node remove(Comparable x, Binary. Node t) throws Item. Not. Found { if (t == null) throw new Intem. Not. Found("Search. Tree remove"); last. Node = t; if (x. less. Than(t. element)) t. left = remove(x, t. left); else { deleted. Node = t; t. right = remove(x, t. right); } if (t == last. Node) { if (deleted. Node == null || x. compares(deleted. Node. element) != 0) throw new Intem. Not. Found("Search. Tree remove"); deleted. Node. element = t. element; deleted. Node = null; t = t. right; } return t; } 13
Udskrivning af elementerne i sorteret rækkefølge 7 15 2 1 5 3 18 9 11 Inorder-traversering af træet void print. Sorted(Binary. Node t) { if (t != null) { print. Sorted(t. left); System. out. println(t. element); print. Sorted(t. right); } } 14
Find det k’te mindste element Vedligehold for hver knude t en variabel, size, der angiver antallet af knuder i det træ, der har t som rod. protected Binary. Node Find. Kth(int k, Binary. Node t) throws Item. Not. Found { if (t == null) throw new Item. Not. Found("BSTWith. Rank find. Kth"); int left. Size = t. left != null ? t. left. size : 0; if (k == left. Size + 1) return t; if (k <= left. Size) return find. Kth(k, t. left); return find. Kth(k - left. Size - 1, t. right); } t left. Size 15
Kompleksiteten af søgning, indsættelse og sletning afhænger af søgetræets udseende. I alle tre tilfælde er tiden proportional med længden af den anvendte søgevej. I bedste fald, nemlig når træet er fuldt, udføres cirka log 2 N sammenligninger. I værste fald, nemlig når træet er en lineær liste, udføres N sammenligninger. 1 3 5 9 16
Det gennemsnitlige tilfælde Hvis hvert element indsættes i tilfældig rækkefølge i et fra starten tomt binært søgetræ, vil længden af søgevejen i det opnåede træ i gennemsnit være 1. 38 log 2 N. I praksis er udførelsestiden for de tre grundoperationer O(log. N) for tilfældigt input. Det er dog endnu ikke blevet påvist analytisk. 17
Balancerede søgetræer Balancering er en teknik, der garanterer, at de værste tilfælde ved søgning ikke forekommer. Ideen er at omorganisere træet under indsættelse og sletning, så det bliver fuldt (eller næsten fuldt). Et fuldt træ siges at være i perfekt balance. For enhver knude gælder nemlig, at antallet af knuder i dens venstre undertræ og antallet af knuder i dens højre undertræ afviger med højst 1. I det følgende præsenteres en række datastrukturer, der garanterer O(log. N) kompleksitet for såvel søgning, indsættelse som sletning. 18
Opbygning af et balanceret søgetræ ud fra en tabel af poster Binary. Search. Tree build. Tree(Comparable[] a) { sort(a); Binary. Search. Tree bst = new Binary. Search. Tree(); bst. root = build. Tree(a, 0, a. length - 1); return bst; } Binary. Node build. Tree(Comparable[] a, int low, int high) { if (low > high) return null; int mid = (low + high)/2; return new Binary. Node(a[mid], build. Tree(a, low, mid - 1), build. Tree(a, mid + 1, high)); } 19
AVL-træer (Adelson-Velskii og Landis, 1962) Et AVL-træ er et binært søgetræ, som opfylder følgende egenskab: For enhver knude i træet gælder, at højden af dens venstre undertræ og højden af dens højre undertræ afviger med højst 1. 20
Eksempel på et AVL-træ Højden af er træ er det maksimale antal af kanter fra træets rod til et af dets blade. For et tomt træ vedtages, at højden er -1. (3) (1) 7 (2) 15 2 (0) (1) 5 9 8 (0) 18 11 (0) 21
Indsættelse i AVL-træ X H H-1 SH-2 Indsættelse i X’s venstre undertræ kan eventuelt ødelægge AVL-egenskaben. I det følgende betegner X den “dybeste” knude, som er rod i et træ, der ikke længere opfylder AVL-egenskaben. 22
Indsættelse i AVL-træ 4 tilfælde Ved indsættelse i et af X’s undertræer er der 4 mulige tilfælde: X 1. Indsættelsen sker i det venstre undertræ af X’s venstre søn. X 2. Indsættelsen sker i det højre undertræ af X’s venstre søn. X 3. Indsættelsen sker i det venstre undertræ af X’s højre søn. X 4. Indsættelsen sker i det højre undertræ af X’s højre søn. Tilfælde 1 og 4 er symmetriske. Tilfælde 2 og 3 er symmetriske. 23
Tilfælde 1 X k 2 k 1 k 2 C A B C En højrerotation genskaber balancen 24
Tilfælde 2 X k 2 k 1 k 2 C A A B B C En højrerotation genskaber ikke balancen 25
Tilfælde 2 (fortsat) k 1 X k 3 k 2 k 1 D A B C k 2 C A B k 3 k 2 D A B C D En venstre-højre-dobbeltrotation genskaber balancen 26
Implementation af højrerotation X k 1 k 2 k 1 C A A B C B static Binary. Node with. Left. Child(Binary. Node k 2) { Binary. Node k 1 = k 2. left; k 2. left = k 1. right; k 1. right = k 2; return k 1; } 27
Implementation af dobbeltrotation k 1 X k 3 k 2 k 1 D A B C k 2 C A B k 3 k 2 D A B C D static binary double. With. Left. Child(Binary. Node k 3) { k 3. left = with. Right. Child(k 3. left); return with. Left. Child(k 3); } 28
Højdeinformation I klassen Binary. Node tilføjes et ekstra felt: int height angiver højden af det træ, der har den angivne knude som rod. Hjælpemetode private static int height(Binary. Node t) { return t == null ? -1 : t. height; } 29
Implementering af metoden insert private Binary. Node insert(Comparable x, Binary. Node t) throws Duplicate. Item { if (t == null) t = new Binary. Node(x, null); else if (x. compares(t. element) < 0 ) { t. left = insert(x, t. left); if (height(t. left) - height(t. right) == 2) if (x. compare. To(t. left. element) < 0) t = Rotations. rotate. With. Left. Child(t); // case 1 else t = Rotations. double. With. Left. Child(t); // case 2 } else if (x. compares(t. element) > 0 ) {. . . // case 3 or 4 } else throw new Duplicate. Item("Search. Tree insert"); t. height = Math. max(height(t. left), height(t. right)) + 1; return t; } 30
Opdatering af height X k 2 k 1 k 2 C A B C static binary with. Left. Child(Binary. Node k 2) { Binary. Node k 1 = k 2. left; k 2. left = k 1. right; k 1. right = k 2; k 2. height = Math. max(height(k 2. left), height(k 2. right)) + 1; k 1. height = Math. max(height(k 1. left), k 2. height) + 1; return k 1; } 31
�Eksempel på indsættelse 60 70 20 10 5 50 30 65 45 indsættes: 85 65 55 60 70 20 10 5 65 50 30 65 85 55 45 fortsættes 32
60 70 20 10 5 50 55 30 65 85 65 45 Venstrerotation ved 20: 60 70 50 20 10 5 65 55 65 85 30 45 fortsættes 33
60 70 50 20 10 5 55 30 65 45 Højrerotation ved 60: 50 20 10 5 85 65 65 60 55 30 45 70 65 85 slut 34
Effektiviteten af AVL-træer Højden H af et AVL-træ tilfredsstiller H < 1. 44 log 2(N+2) - 1. 328 I et tilfældigt konstrueret træ er højden meget tæt på log 2(N). 35
Problem Et skakbræt med 8 x 8 felter kan dækkes af 32 dominobrikker, som hver dækker 2 af brættets felter. To af brættets hjørnefelter på samme diagonal skæres væk. Kan 31 brikker nu dække brættet? Farvelægning løser problemet. 36
Rød-Sort-træer (Guibas og Sedgewick, 1978) Et Rød-Sort-træ er et binært søgetræ, som opfylder følgende 4 egenskaber: 1. Enhver knude er farvet enten rød eller sort. 2. Roden er sort. 3. Hvis en knude er rød, så er dens sønner sorte. 4. Enhver vej fra roden til en null-reference indeholder det samme antal sorte knuder. 37
Eksempel på et Rød-Sort-træ 30 70 15 10 20 50 5 40 85 60 65 80 90 55 0. Træet er et binært søgetræ. 1. Enhver knude er farvet enten rød eller sort. 2. Roden er sort. 3. Hvis en knude er rød, så er dens sønner sorte. (null regnes for sort) 4. Enhver vej fra rod til blad indeholder det samme antal sorte knuder. (3) 38
Effektiviteten af Rød-Sort-træer Højden H af et Rød-Sort-træ tilfredsstiller H ≤ 2 log 2(N+1) I et tilfældigt konstrueret træ er højden meget tæt på log 2(N). (faktisk 1. 002 log 2(N)) 39
Indsættelse i Rød-Sort-træer En ny knude indsættes (som sædvanligt) som nyt blad i træet. Hvis den nye knude farves sort, ødelægges rød-sort-egenskab 4. Det er ikke umiddelbart klart, hvorledes egenskaben kan genoprettes. Hvis den nye knude farves rød, og dens far samtidig er sort, vil ingen af rød-sort-egenskaberne blive ødelagt. Hvis dens far derimod er rød, ødelægges rød-sort-egenskab 3. Vi skal sørge for, at en ny knude indsættes som rød søn af en sort far. Hvordan? Svar: Benyt rotationer og farveskift. 40
Behandling af 5 tilfælde X: den aktuelle røde knude. P: X’s røde far. G: X’s farfar (må nødvendigvis være sort) S: X’s farbror Tilfælde 1: X er venstre-søn til P, P er venstre-søn til G, og S er sort. P G P S X X G G S S X A P C B A A B rotatewith. Left. Child(G) C B C Skift farve på P og G 41
Tilfælde 2: X er højre-søn til P, P er venstre-søn til G, og S er sort. G X G P X S S P X C B 2 S C A B 1 G P A B 1 A B 2 X with. Left. Child(G) P with. Right. Child(P) C G S Skift farve på X og G A B 1 B 2 C 42
Tilfælde 3: X er højre-søn til P, P er højre-søn til G, og S er sort. Er symmetrisk med tilfælde 1 Tilfælde 4: X er venstre-søn til P, P er højre-søn til G, og S er sort. Er symmetrisk med tilfælde 2 Tilfælde 5: Både P og S er røde. G P P S X A G C B S X A C B Skift farve på P, S og G. Hvis G er rod, så farv G sort. 43
I tilfælde 5 kan en rød-farvning af G ødelægge rød-sort-egenskab 3. Dette problem kan dog let løses ved en enkelt-rotation (tilfælde 1 og 3) eller en dobbelt-rotation (tilfælde 2 og 4). Ingen af disse rotationer giver i sig selv anledning til yderligere rotationer. Rotationerne af type 5 kræver adgang til X’s oldefar. I lærebogens algoritme vedligeholdes således følgende referencer: current: parent: grand: great: den aktuelle knudes far den aktuelle knudes bedstefar den aktuelle knudes oldefar Disse referencer kan undværes, hvis indsættelse foretages rekursivt. Dette vil blive beskrevet i det følgende. 44
Implementering I klassen Binary. Node tilføjes feltet int color; I klassen Red. Black. Tree defineres konstanterne static final int RED = 0; static final int BLACK = 1; I stedet for null-referencer benyttes objektet null. Node: static Binary. Node null. Node; static { null. Node = new Binary. Node(null); null. Node. left = null. Node. right = null. Node; null. Node. color = BLACK; } 45
public void insert(Comparable x) throws Duplicate. Item { root = insert(x, root, true); root. color = BLACK; } private Binary. Node insert(Comparable x, Binary. Node t, boolean from. Right) throws Duplicate. Item { if (t == null. Node) { t = new Binary. Node(x, null. Node); t. color = RED; } else { if (t. left. color == RED && t. right. color == RED) { t. color = RED; t. left. color = t. right. color = BLACK; } if (x. compares(t. element) < 0) { t. left = insert(x, t. left, false); if (from. Right && t. color == RED && t. left. color == RED) t = Rotations. with. Left. Child(t); if (t. left. color == RED && t. left. color == RED) { t = Rotations. with. Left. Child(t); t. color = BLACK; t. right. color = RED; } } else if (x. compares(t. element) > 0) {. . . } else throw new Duplicate. Item("Red. Black. Tree insert"); } return t; } 46
Behandling af de 2 symmetriske tilfælde left erstattes med right erstattes med left from. Right erstattes med !from. Right t. right = insert(x, t. right, true); if (!from. Right && t. color == RED && t. right. color == RED) t = Rotations. with. Right. Child(t); if (t. right. color == RED && t. right. color == RED) { t = Rotations. with. Right. Child(t); t. color = BLACK; t. left. color = RED; } 47
Eksempel på indsættelse 30 70 15 10 20 50 5 40 85 60 65 80 90 30 70 15 55 10 20 85 60 45 indsættes: 50 5 Farveskift på 50, 40 og 55: 40 65 80 90 55 45 fortsættes 48
30 70 15 10 20 50 5 85 60 40 65 80 55 90 30 15 45 10 Højrerotation ved 70 med farveskift af 60 og 70: 5 60 20 50 40 70 85 55 65 45 80 90 slut 49
AVL-træer contra Rød-Sort-træer Et rød-sort-træ er sædvanligvis mere effektivt: Indsættelse i et AVL-træ kræver (i værste tilfælde) 2 gennemløb af en vej (ned til et blad og tilbage til roden), mens indsættelse i et rød-sort-træ kan klares på 1 gennemløb. NB. I den rekursive implementation for et rød-sort-træ benyttes 2 gennemløb. Implementation af sletning i såvel AVL- som rød-sort-træer er vanskelig. 50
AA-træer Et AA-træ er et rød-sort-træ, som opfylder en ekstra betingelse: (5) En venstre-søn må ikke være rød. Betingelsen forenkler implementering: (a) antallet af omstruktureringstilfælde halveres (b) et besværligt tilfælde ved sletning i et rød-sort-træ elimineres 51
Figurlig beskrivelse af AA-træer Niveau erstatter farve. En knudes niveau er • 1, hvis knuden er et blad • lig med sin fars niveau, hvis knuden er rød • 1 mindre end sin fars niveau, hvis knuden er sort 70 30 15 5 10 50 20 35 40 niveau 3 60 55 niveau 2 85 65 80 90 niveau 1 52
Egenskaber 70 30 15 5 10 1. 2. 3. 4. 50 20 35 40 60 55 85 65 80 90 Vandrette hægter peger mod højre Der er ikke to konsekutive vandrette hægter Enhver knude på niveau 2 eller højere har mindst to børn Hvis en knude på niveau 2 eller højere ikke har en vandret hægte, så må dens to børn være på samme niveau 53
Rotationer kan opretholde AA-egenskaberne Der er kun 2 tilfælde, der kræver omstrukturering: Tilfælde 1 (vandret venstre-hægte): X P A B X P C A B C private Binary. Node skew(Binary. Node t) { if (t. left. level == t. level) t = Rotations. with. Left. Child(t); return t; } 54
Tilfælde 2 (to konsekutive vandrette hægter): R X A R B X G A G B private Binary. Node split(Binary. Node t) { if (t. right. level == t. level) { t = Rotations. with. Right. Child(t); t. level++; } return t; } Efter skew kan en split være nødvendig 55
Metoden insert Benyt rekursion og kald skew og split på tilbagevejen. private Binary. Node insert(Comparable x, Binary. Node t) throws Duplicate. Item { if (t == null. Node) t = new Binary. Node(x, null. Node); else if (x. compares(t. element) < 0) t. left = insert(x, t. left); else if (x. compares(t. element) > 0) t. right = insert(x, t. right); else throw new Duplicate. Item("Search. Tree insert"); return split(skew(t)); } 56
Eksempel på indsættelse 70 30 15 5 10 50 20 35 60 40 55 85 65 80 90 45 indsættes: 70 30 15 5 10 50 20 35 40 60 45 55 85 65 80 90 fortsættes 57
70 30 15 5 10 50 20 35 40 60 45 55 85 65 80 90 split ved 35: 70 30 15 5 10 skew ved 50: 20 35 10 55 85 65 80 90 70 40 20 60 45 30 15 5 50 40 35 50 45 60 55 85 65 80 90 fortsættes 58
70 30 15 5 10 split ved 40: 40 20 35 10 skew ved 70: 55 50 20 10 40 20 55 50 30 35 80 90 85 65 80 90 70 60 45 65 60 45 35 85 70 40 15 5 60 45 30 15 5 50 55 85 65 80 90 fortsættes 59
50 30 40 15 5 10 70 20 35 60 45 split ved 30: 55 85 65 90 50 70 30 40 15 5 80 10 20 35 60 45 55 85 65 80 90 slut 60
Metoden remove Benyt rekursion og kald skew og split på tilbagevejen. Binary. Node remove(Comparable x, Binary. Node t) throws Item. Not. Found { if (t == null. Node) return null. Node; last. Node = t; if (x. less. Than(t. element)) t. left = remove(x, t. left); else { deleted. Node = t; t. right = remove(x, t. right); } if (t == last. Node) { if (deleted. Node == null. Node || x. compares(deleted. Node. element) != 0) throw new Item. Not. Found("AATree remove"); deleted. Node. element = t. element; deleted. Node = null. Node; t = t. right; } else { /* se næste side */ } return t; } 61
Opretholdelse af AA-egenskaben if (t. left. level < t. level - 1 || t. right. level < t. level - 1 ) { t. level--; if (t. right. level > t. level) t. right. level = t. level; t = skew(t); t. right = skew(t. right); t = split(t); t. right = split(t. right); } Se lærebogen forklaring 62
Eksempel på sletning 5 2 1 1 slettes: 3 t 2 4 6 7 5 3 null. Node 5 t. level--: t 2 t. right. level--: 2 3 t 5 3 4 fortsættes 63
t 2 3 5 6 7 4 t = skew(t): ingen effekt t. right = skew(t. right): t 2 3 4 5 6 7 fortsættes 64
2 5 4 3 6 7 t = split(t): 3 t 2 4 5 6 7 t. right = split(t. right): 3 2 t 5 4 6 7 slut 65
Måling af tidsforbrug Indsættelse af 300, 000 forskellige heltal i et fra starten tomt træ. Metrowerks, 400 MHz Power. Book. AVL-træ Rød-sort-træ (ikke-rekursiv version) Rød-sort (java. util. Tree. Set) AA-træ 6. 8 sekunder 7. 2 sekunder 6. 6 sekunder 6. 9 sekunder 7. 0 sekunder 66
B-træ en datastruktur til ekstern søgning (Bayer og Mc. Craight, 1970) 10, 000 poster ønskes lagret på en disk på en sådan måde, at søgetiden bliver kort. Almindeligt binært træ: Det gennemsnitlige tilfælde: 1. 38*log 2(10, 000) ≈ 32 tilgange til disken Det værste tilfælde: 10, 000 tilgange! Balanceret binært træ: cirka log 2(10, 000) ≈ 24 tilgange Dette er uacceptabelt. Benyt et B-træ - et balanceret flervejstræ. 67
B-træ af orden 5 nøgler poster 68
Definition af B-træ Et B-træ af orden M er et M-vejs træ med følgende egenskaber: 1. Posterne er lagret i træets blade. 2. De interne knuder kan indeholde op til M-1 nøgler. Nøgle i er den mindste nøgle i undertræ i +1. 3. Roden er enten et blad eller har mellem 2 og M børn. 4. Alle interne knuder, undtagen roden, har mellem ÈM/2 og M børn. 5. Alle blade er på den samme dybde og indeholder mellem ÈL/2 og L poster. (Gælder dog kun hvis træet indeholder mindst ÈL/2 poster) 69
Effektivitet ved brug af et B-træ Antag • • at hver af de 10, 000 poster fylder 256 bytes at hver nøgle fylder 32 bytes at hver diskhenvisning fylder 4 bytes at blokstørrelsen er 8, 192 bytes. Vælg M så stor som mulig, og (M-1)*32 + M*4 ≤ 8192, altså M = 228. Hver intern knude har mindst ÈM/2 = 114 sønner. L = 8192/256 = 32. Antal blade: højst 10, 000/ÈL/2 = 10, 000/16 = 625, 000. Antal niveauer i træet log 114(625, 000) ≈ 3. 4. Alle blade er på niveau 4. Hvis roden ligger i RAM, kræves derfor kun 3 tilgange til disken for at finde en post. 70
Indsættelse af 57 simpel 71
Indsættelse af 55 medfører 1 splitning 72
Indsættelse af 40 medfører 2 splitninger 73
Sletning af 99 74
Skitse til implementering af B-træer public class BTree { private int M, height; private Node root; private class Node{. . . } public BPTree(int order) { M = order; } public Object find(Comparable key) {. . . } public void insert(Comparable key, Object data) {. . . } boolean remove(Comparable key) {. . . } } 75
class Entry { Comparable key; Object pointer; Entry(Comparable k, Object p) { key = k; pointer = p; } } class Node { Entry[] entry = new Entry[M + 1]; int size; Object find(Comparable key, int ht) {. . . } Node insert(Comparable key, Object data, int ht) {. . . } Node split() {. . . } } 76
search Object search(Comparable key) { return root != null ? root. find(key, height) : null; } Object find(Comparable key, int ht) { if (ht == 0) { for (int i = 0; i < size; i++) if (key. compares(entry[i]. key) == 0) return entry[i]. pointer; } else for (int i = 0; i < size; i++) if (i + 1 == size || key. compares(entry[i + 1]. key) < 0) return ((Node) entry[i]. pointer). find(key, ht - 1); return null; } 77
void insert(Comparable key, Object data) { if (root == null) root = new Node(); Node t = root. insert(key, data, height); if (t != null) { // split root Node new. Root = new Node(); new. Root. entry[0] = new Entry(root. entry[0]. key, root); new. Root. entry[1] = new Entry(t. entry[0]. key, t); root = new. Root; root. size = 2; height++; } } 78
Node insert(Comparable key, Object data, int ht) { Entry new. Entry = new Entry(key, data); int i; if (ht == 0) { for (i = 0; i < size; i++) if (key. compares(entry[i]. key) < 0) break; } else for (i = 0; i < size; i++) if (i + 1 == size || key. compare. To(entry[i+1]. key) < 0) Node t = ((Node) entry[i++]. pointer). insert(key, data, ht - 1); if (t == null) return null; new. Entry. key = t. entry[0]. key; new. Entry. pointer = t; break; } for (int j = size; j > i; j--) entry[j] = entry[j - 1]; entry[i] = new. Entry; return ++size <= M ? null : split(); } { 79
Node split() { Node t = new Node(); for (int i = 0, j = M/2; j <= M; i++, j++) t. entry[i] = entry[j]; t. size = M - M/2 + 1; size = M/2; return t; } 80
Ugeseddel 9 6. november - 13. november • Læs kapitel 19 og 20 i lærebogen (side 553 -613) • Løs følgende opgaver 9 -1. Opgave 18. 1 9 -2. Opgave 18. 5 9 -3. Opgave 18. 12 9 -4. Opgave 18. 16 9 -5. Opgave 18. 17 81
- Slides: 81