|
Hauptseite - Welches System? - Hardware - Software - Emulatoren - |
Internet MausNet Programmieren Verweise Über |
Die folgenden Beispiele zeigen einen ausbalancierten AVL-Baum.
Sprache | C | Pascal | Modula |
---|---|---|---|
Beispiel | avl.c | avl.pas | avl.mod |
/* Da der Datentyp des AVL-Baums erst bei einer konkreten */ /* Anwendung feststeht, ist der Baum nur als Beispiel und */ /* nicht als Modul programmiert. */ #include#include #define AVL_MAX_HEIGHT 32 typedef long AvlKeyType; typedef struct avl_knoten { AvlKeyType Key; short Bal; short cache; /* Used during insertion */ struct avl_knoten *Link[2]; } AvlElement, *AvlKnoten; typedef AvlKnoten AvlBaum; void AvlCreate(AvlBaum *tree) { *tree = NULL; } void AvlInsert(AvlBaum *tree, AvlKeyType key) { /* Uses Knuth's Algorithm 6.2.3A (balanced tree search and insertion), but caches results of comparisons. In empirical tests this eliminates about 25% of the comparisons seen under random insertions. */ /* A1. */ AvlKnoten t, s, p, q, r, this; this = malloc(sizeof(AvlElement)); if (this != NULL) { this->Bal = 0; if (*tree == NULL) *tree = this; else { t = *tree; s = p = *tree; for (;;) { /* A2. */ /* compare, included in A3, Michael Bernstein */ /* A3. */ if (key < p->Key) { p->cache = 0; q = p->Link[0]; if (q == NULL) { p->Link[0] = q = this; break; } } /* A4. */ else if (key > p->Key) { p->cache = 1; q = p->Link[1]; if (q == NULL) { p->Link[1] = q = this; break; } } /* A3, A4. */ if (q->Bal != 0) { t = p; s = q; } p = q; } /* A5. */ this->Link[0] = NULL; this->Link[1] = NULL; /* A6. */ r = p = s->Link[s->cache]; while (p != q) { p->Bal = p->cache * 2 - 1; p = p->Link[p->cache]; } /* A7. */ if (s->cache == 0) { /* a = -1. */ if (s->Bal == 0) { s->Bal = -1; return; } else if (s->Bal == 1) { s->Bal = 0; return; } if (r->Bal == -1) { /* A8. */ p = r; s->Link[0] = r->Link[1]; r->Link[1] = s; s->Bal = r->Bal = 0; } else { /* A9. */ p = r->Link[1]; r->Link[1] = p->Link[0]; p->Link[0] = r; s->Link[0] = p->Link[1]; p->Link[1] = s; if (p->Bal == -1) { s->Bal = 1; r->Bal = 0; } else if (p->Bal == 0) s->Bal = r->Bal = 0; else { s->Bal = 0; r->Bal = -1; } p->Bal = 0; } } else { /* a == +1. */ if (s->Bal == 0) { s->Bal = 1; return; } else if (s->Bal == -1) { s->Bal = 0; return; } if (r->Bal == 1) { /* A8. */ p = r; s->Link[1] = r->Link[0]; r->Link[0] = s; s->Bal = r->Bal = 0; } else { /* A9. */ p = r->Link[0]; r->Link[0] = p->Link[1]; p->Link[1] = r; s->Link[1] = p->Link[0]; p->Link[0] = s; if (p->Bal == 1) { s->Bal = -1; r->Bal = 0; } else if (p->Bal == 0) s->Bal = r->Bal = 0; else { s->Bal = 0; r->Bal = 1; } p->Bal = 0; } } /* A10. */ /*if (t != *tree && s == t->Left)*/ if (s == t->Link[1]) t->Link[1] = p; else if (s == t->Link[0]) t->Link[0] = p; else *tree = p; } } } void AvlRemove(AvlBaum *tree, AvlKeyType Key) { /* Uses my Algorithm D, which can be found at http://www.msu.edu/user/pfaffben/avl. Algorithm D is based on Knuth's Algorithm 6.2.2D (Tree deletion) and 6.2.3A (Balanced tree search and insertion), as well as the notes on pages 465-466 of Vol. 3. */ /* D1. */ AvlElement Dummy; AvlKnoten pa[AVL_MAX_HEIGHT]; /* Stack P: Nodes. */ short a[AVL_MAX_HEIGHT]; /* Stack P: Bits. */ int k; /* Stack P: Pointer. */ AvlKnoten *q, p, r, s; int l; /* insert dummy entry because access to k-1 is used */ /* and this can generate access to pa[0], but we dont */ /* want to modify any node in the tree */ a[0] = 0; pa[0] = &Dummy; Dummy.Key = 0; Dummy.Link[0] = NULL; Dummy.Link[1] = NULL; p = *tree; k = 1; for (;;) { /* D2. */ if (p == NULL) return; if (Key == p->Key) break; /* D3, D4. */ pa[k] = p; if (Key < p->Key) { p = p->Link[0]; a[k] = 0; } else if (Key > p->Key) { p = p->Link[1]; a[k] = 1; } k++; } /* D5. */ q = &(pa[k - 1]->Link[a[k - 1]]); if (p->Link[1] == NULL) { *q = p->Link[0]; if (*q) (*q)->Bal = 0; } else { /* D6. */ r = p->Link[1]; if (r->Link[0] == NULL) { r->Link[0] = p->Link[0]; *q = r; r->Bal = p->Bal; a[k] = 1; pa[k++] = r; } else { /* D7. */ s = r->Link[0]; l = k++; a[k] = 0; pa[k++] = r; /* D8. */ while (s->Link[0] != NULL) { r = s; s = r->Link[0]; a[k] = 0; pa[k++] = r; } /* D9. */ a[l] = 1; pa[l] = s; s->Link[0] = p->Link[0]; r->Link[0] = s->Link[1]; s->Link[1] = p->Link[1]; s->Bal = p->Bal; *q = s; } } if (p == *tree) { /* Michael Bernstein: delete tree, we had to set new tree */ *tree = *q; } /* Michael Bernstein: else tree is unchanged */ free(p); /* D10. */ while (--k) { s = pa[k]; if (a[k] == 0) { /* D10. */ if (s->Bal == -1) { s->Bal = 0; continue; } else if (s->Bal == 0) { s->Bal = 1; break; } r = s->Link[1]; if (r->Bal == 0) { /* D11. */ s->Link[1] = r->Link[0]; r->Link[0] = s; r->Bal = -1; pa[k - 1]->Link[a[k - 1]] = r; if (*tree == s) { /* Michael Bernstein: if k == 1 we have to set new root into tree */ *tree = r; } break; } else if (r->Bal == 1) { /* D12. */ s->Link[1] = r->Link[0]; r->Link[0] = s; s->Bal = r->Bal = 0; pa[k - 1]->Link[a[k - 1]] = r; if (*tree == s) { /* Michael Bernstein: if k == 1 we have to set new root into tree */ *tree = r; } } else { /* D13. */ p = r->Link[0]; r->Link[0] = p->Link[1]; p->Link[1] = r; s->Link[1] = p->Link[0]; p->Link[0] = s; if (p->Bal == 1) { s->Bal = -1; r->Bal = 0; } else if (p->Bal == 0) s->Bal = r->Bal = 0; else { s->Bal = 0; r->Bal = 1; } p->Bal = 0; pa[k - 1]->Link[a[k - 1]] = p; if (*tree == s) { /* Michael Bernstein: if k == 1 we have to set new root into tree */ *tree = p; } } } else { /* D10. */ if (s->Bal == 1) { s->Bal = 0; continue; } else if (s->Bal == 0) { s->Bal = -1; break; } r = s->Link[0]; if (r->Bal == 0) { /* D11. */ s->Link[0] = r->Link[1]; r->Link[1] = s; r->Bal = 1; pa[k - 1]->Link[a[k - 1]] = r; if (*tree == s) { /* Michael Bernstein: if k == 1 we have to set new root into tree */ *tree = r; } break; } else if (r->Bal == -1) { /* D12. */ s->Link[0] = r->Link[1]; r->Link[1] = s; s->Bal = r->Bal = 0; pa[k - 1]->Link[a[k - 1]] = r; if (*tree == s) { /* Michael Bernstein: if k == 1 we have to set new root into tree */ *tree = r; } } else if (r->Bal == 1) { /* D13. */ p = r->Link[1]; r->Link[1] = p->Link[0]; p->Link[0] = r; s->Link[0] = p->Link[1]; p->Link[1] = s; if (p->Bal == -1) { s->Bal = 1; r->Bal = 0; } else if (p->Bal == 0) s->Bal = r->Bal = 0; else { s->Bal = 0; r->Bal = -1; } p->Bal = 0; pa[k - 1]->Link[a[k - 1]] = p; if (*tree == s) { /* Michael Bernstein: if k == 1 we have to set new root into tree */ *tree = p; } } } } } AvlKnoten AvlFind(AvlBaum tree, AvlKeyType Key) { #if 0 /* rekursive Loesung */ if (k < tree->key) { if (tree->Link[0] != NULL) return(AvlFind(tree->Link[0], Key)); else return(NULL); } else if (k > tree->key) { if (tree->Link[1] != NULL) return(AvlFind(tree->Link[1], Key)); else return(NULL); } else return(tree); #else AvlKnoten PresentPtr; /* iterativ, schneller als rekursiv */ PresentPtr = tree; while ((PresentPtr != NULL) && (PresentPtr->Key != Key)) { if (Key < PresentPtr->Key) PresentPtr = PresentPtr->Link[0]; else if (Key > PresentPtr->Key) PresentPtr = PresentPtr->Link[1]; } return(PresentPtr); #endif }
(* Da der Datentyp des AVL-Baums erst bei einer konkreten *) (* Anwendung feststeht, ist der Baum nur als Beispiel und *) (* nicht als Modul programmiert. *) const AvlMaxHeight = 32; type AvlKeyType = long_integer; AvlKnoten = ^AvlElement; AvlElement = record Key : AvlKeyType; Bal : integer; cache : integer; (* Used during insertion *) Link : array[0..1] of AvlKnoten; end; AvlBaum = AvlKnoten; procedure AvlCreate(var tree : AvlBaum); begin tree := nil; end; procedure AvlInsert(var tree : AvlBaum; Key: AvlKeyType); (* Uses Knuth's Algorithm 6.2.3A (balanced tree search and insertion), but caches results of comparisons. In empirical tests this eliminates about 25% of the comparisons seen under random insertions. *) var (* A1. *) t, s, p, q, r, this : AvlKnoten; fertig : boolean; begin new(this); this^.Key := Key; this^.Bal := 0; if (tree = nil) then tree := this else begin t := tree; s := tree; p := tree; fertig := false; while not fertig do begin (* A2. *) (* compare, included in A3, Michael Bernstein *) (* A3. *) if (key < p^.Key) then begin p^.cache := 0; q := p^.Link[0]; if (q = nil) then begin p^.Link[0] := this; q := this; fertig := true; end; end > p^.Key) then begin p^.cache := 1; q := p^.Link[1]; if (q = nil) then begin p^.Link[1] := this; q := this; fertig := true; end; end; if not fertig then begin (* A3, A4. *) if (q^.Bal <> 0) then begin t := p; s := q; end; p := q; end; end; (* A5. *) this^.Link[0] := nil; this^.Link[1] := nil; (* A6. *) r := s^.Link[s^.cache]; p := s^.Link[s^.cache]; while (p <> q) do begin p^.Bal := p^.cache * 2 - 1; p := p^.Link[p^.cache]; end; (* A7. *) fertig := false; if (s^.cache = 0) then begin (* a := -1. *) if (s^.Bal = 0) then begin s^.Bal := -1; fertig := true; end else if (s^.Bal = 1) then begin s^.Bal := 0; fertig := true; end else if (r^.Bal = -1) then begin (* A8. *) p := r; s^.Link[0] := r^.Link[1]; r^.Link[1] := s; s^.Bal := 0; r^.Bal := 0; end else begin (* A9. *) p := r^.Link[1]; r^.Link[1] := p^.Link[0]; p^.Link[0] := r; s^.Link[0] := p^.Link[1]; p^.Link[1] := s; if (p^.Bal = -1) then begin s^.Bal := 1; r^.Bal := 0; end else if (p^.Bal = 0) then begin s^.Bal := 0; r^.Bal := 0; end else begin s^.Bal := 0; r^.Bal := -1; end; p^.Bal := 0; end; end else begin (* a = +1. *) if (s^.Bal = 0) then begin s^.Bal := 1; fertig := true; end else if (s^.Bal = -1) then begin s^.Bal := 0; fertig := true; end else if (r^.Bal = 1) then begin (* A8. *) p := r; s^.Link[1] := r^.Link[0]; r^.Link[0] := s; s^.Bal := 0; r^.Bal := 0; end else begin (* A9. *) p := r^.Link[0]; r^.Link[0] := p^.Link[1]; p^.Link[1] := r; s^.Link[1] := p^.Link[0]; p^.Link[0] := s; if (p^.Bal = 1) then begin s^.Bal := -1; r^.Bal := 0; end else if (p^.Bal = 0) then begin s^.Bal := 0; r^.Bal := 0; end else begin s^.Bal := 0; r^.Bal := 1; end; p^.Bal := 0; end; end; (* A10. *) if not fertig then begin (*if (t <> *tree && s = t^.Left)*) if (s = t^.Link[1]) then t^.Link[1] := p else if (s = t^.Link[0]) then t^.Link[0] := p else tree := p; end; end; end; procedure AvlRemove(var tree : AvlBaum; Key : AvlKeyType); (* Uses my Algorithm D, which can be found at http://www.msu.edu/user/pfaffben/avl. Algorithm D is based on Knuth's Algorithm 6.2.2D (Tree deletion) and 6.2.3A (Balanced tree search and insertion), as well as the notes on pages 465-466 of Vol. 3. *) var (* D1. *) pa : array[0..AvlMaxHeight] of AvlKnoten; (* Stack P: Nodes. *) a : array[0..AvlMaxHeight] of integer; (* Stack P: Bits. *) k : integer; (* Stack P: Pointer. *) p, q, r, s : AvlKnoten; l : integer; fertig : boolean; begin (* insert dummy entry because access to k-1 is used *) (* and this can generate access to pa[0], but we dont *) (* want to modify any node in the tree *) a[0] := 0; new(pa[0]); pa[0]^.Key := 0; pa[0]^.Link[0] := nil; pa[0]^.Link[1] := nil; p := tree; k := 1; fertig := false; while not fertig do begin (* D2. *) if (p = nil) then fertig := true else if (Key = p^.Key) then fertig := true else begin (* D3, D4. *) pa[k] := p; if (Key < p^.Key) then begin p := p^.Link[0]; a[k] := 0; end else if (Key > p^.Key) then begin p := p^.Link[1]; a[k] := 1; end; k := k + 1; end; end; if p<>nil then begin (* D5. *) if (p^.Link[1] = nil) then begin pa[k - 1]^.Link[a[k - 1]] := p^.Link[0]; if (pa[k - 1]^.Link[a[k - 1]] <> nil) then pa[k - 1]^.Link[a[k - 1]]^.Bal := 0; end else begin (* D6. *) r := p^.Link[1]; if (r^.Link[0] = nil) then begin r^.Link[0] := p^.Link[0]; q := r; r^.Bal := p^.Bal; a[k] := 1; pa[k] := r; k := k + 1; end else begin (* D7. *) s := r^.Link[0]; l := k; k := k + 1; a[k] := 0; pa[k] := r; k := k + 1; (* D8. *) while (s^.Link[0] <> nil) do begin r := s; s := r^.Link[0]; a[k] := 0; pa[k] := r; k := k + 1; end; (* D9. *) a[l] := 1; pa[l] := s; s^.Link[0] := p^.Link[0]; r^.Link[0] := s^.Link[1]; s^.Link[1] := p^.Link[1]; s^.Bal := p^.Bal; q := s; end; end; if (p = tree) then (* Michael Bernstein: delete tree, we had to set new tree *) tree := q; (* Michael Bernstein: else tree is unchanged *) dispose(p); (* D10. *) k := k - 1; while (k > 0) do begin fertig := false; s := pa[k]; if (a[k] = 0) then begin (* D10. *) if (s^.Bal = -1) then begin s^.Bal := 0; fertig := true; end else if (s^.Bal = 0) then begin s^.Bal := 1; fertig := true; k := 0; (* to nd loop *) end; if not fertig then begin r := s^.Link[1]; if (r^.Bal = 0) then begin (* D11. *) s^.Link[1] := r^.Link[0]; r^.Link[0] := s; r^.Bal := -1; pa[k - 1]^.Link[a[k - 1]] := r; if (tree = s) then (* Michael Bernstein: if k = 1 we have to set new root into tree *) tree := r; fertig := true; k := 0; (* to end loop *) end else if (r^.Bal = 1) then begin (* D12. *) s^.Link[1] := r^.Link[0]; r^.Link[0] := s; s^.Bal := 0; r^.Bal := 0; pa[k - 1]^.Link[a[k - 1]] := r; if (tree = s) then (* Michael Bernstein: if k = 1 we have to set new root into tree *) tree := r; end else begin (* D13. *) p := r^.Link[0]; r^.Link[0] := p^.Link[1]; p^.Link[1] := r; s^.Link[1] := p^.Link[0]; p^.Link[0] := s; if (p^.Bal = 1) then begin s^.Bal := -1; r^.Bal := 0; end else if (p^.Bal = 0) then begin s^.Bal := 0; r^.Bal := 0; end else begin s^.Bal := 0; r^.Bal := 1; end; p^.Bal := 0; pa[k - 1]^.Link[a[k - 1]] := p; if (tree = s) then (* Michael Bernstein: if k = 1 we have to set new root into tree *) tree := p; end; end; end else begin (* D10. *) if (s^.Bal = 1) then begin s^.Bal := 0; fertig := true; end else if (s^.Bal = 0) then begin s^.Bal := -1; fertig := true; k := 0; (* to end loop *) end; if not fertig then begin r := s^.Link[0]; if (r^.Bal = 0) then begin (* D11. *) s^.Link[0] := r^.Link[1]; r^.Link[1] := s; r^.Bal := 1; pa[k - 1]^.Link[a[k - 1]] := r; if (tree = s) then (* Michael Bernstein: if k = 1 we have to set new root into tree *) tree := r; fertig := true; k := 0; (* to end loop *) end else if (r^.Bal = -1) then begin (* D12. *) s^.Link[0] := r^.Link[1]; r^.Link[1] := s; s^.Bal := 0; r^.Bal := 0; pa[k - 1]^.Link[a[k - 1]] := r; if (tree = s) then (* Michael Bernstein: if k = 1 we have to set new root into tree *) tree := r; end else if (r^.Bal = 1) then begin (* D13. *) p := r^.Link[1]; r^.Link[1] := p^.Link[0]; p^.Link[0] := r; s^.Link[0] := p^.Link[1]; p^.Link[1] := s; if (p^.Bal = -1) then begin s^.Bal := 1; r^.Bal := 0; end else if (p^.Bal = 0) then begin s^.Bal := 0; r^.Bal := 0; end else begin s^.Bal := 0; r^.Bal := -1; end; p^.Bal := 0; pa[k - 1]^.Link[a[k - 1]] := p; if (tree = s) then (* Michael Bernstein: if k = 1 we have to set new root into tree *) tree := p; end; end; end; k := k - 1; end; end; dispose(pa[0]); end; function AvlFind(tree : AvlBaum; Key : AvlKeyType):AvlKnoten; var PresentPtr : AvlKnoten; Found : boolean; begin (* iterativ, schneller als rekursiv *) PresentPtr := tree; Found := false; while not Found do begin if (PresentPtr = nil) then Found := true else if (PresentPtr^.Key = Key) then Found := true else if (Key < PresentPtr^.Key) then PresentPtr := PresentPtr^.Link[0] else if (Key > PresentPtr^.Key) then PresentPtr := PresentPtr^.Link[1]; end; AvlFind := PresentPtr; end;
(* Da der Datentyp des AVL-Baums erst bei einer konkreten *) (* Anwendung feststeht, ist der Baum nur als Beispiel und *) (* nicht als Modul programmiert. *) FROM Heap IMPORT Allocate, Deallocate; FROM SYSTEM IMPORT TSIZE; CONST AvlMaxHeight = 32; TYPE AvlKeyType = LONGINT; AvlKnoten = POINTER TO AvlElement; AvlElement = RECORD Key : AvlKeyType; Bal : INTEGER; cache : INTEGER; (* Used during insertion *) Link : ARRAY[0..1] OF AvlKnoten; END; AvlBaum = AvlKnoten; PROCEDURE AvlCreate(VAR tree : AvlBaum); BEGIN tree := NIL; END AvlCreate; PROCEDURE AvlInsert(VAR tree : AvlBaum; Key: AvlKeyType); (* Uses Knuth's Algorithm 6.2.3A (balanced tree search and insertion), but caches results of comparisons. In empirical tests this eliminates about 25% of the comparisons seen under random insertions. *) VAR (* A1. *) t, s, p, q, r, this : AvlKnoten; fertig : BOOLEAN; BEGIN Allocate(this,TSIZE(AvlElement)); this^.Key := Key; this^.Bal := 0; IF (tree = NIL) THEN tree := this; ELSE t := tree; s := tree; p := tree; fertig := FALSE; WHILE NOT fertig DO (* A2. *) (* compare, included in A3, Michael Bernstein *) (* A3. *) IF (Key < p^.Key) THEN p^.cache := 0; q := p^.Link[0]; IF (q = NIL) THEN p^.Link[0] := this; q := this; fertig := TRUE; END; (* A4. *) ELSIF (Key > p^.Key) THEN p^.cache := 1; q := p^.Link[1]; IF (q = NIL) THEN p^.Link[1] := this; q := this; fertig := TRUE; END; END; IF NOT fertig THEN (* A3, A4. *) IF (q^.Bal <> 0) THEN t := p; s := q; END; p := q; END; END; (* A5. *) this^.Link[0] := NIL; this^.Link[1] := NIL; (* A6. *) r := s^.Link[s^.cache]; p := s^.Link[s^.cache]; WHILE (p <> q) DO p^.Bal := p^.cache * 2 - 1; p := p^.Link[p^.cache]; END; (* A7. *) fertig := FALSE; IF (s^.cache = 0) THEN (* a := -1. *) IF (s^.Bal = 0) THEN s^.Bal := -1; fertig := TRUE; ELSIF (s^.Bal = 1) THEN s^.Bal := 0; fertig := TRUE; ELSIF (r^.Bal = -1) THEN (* A8. *) p := r; s^.Link[0] := r^.Link[1]; r^.Link[1] := s; s^.Bal := 0; r^.Bal := 0; ELSE (* A9. *) p := r^.Link[1]; r^.Link[1] := p^.Link[0]; p^.Link[0] := r; s^.Link[0] := p^.Link[1]; p^.Link[1] := s; IF (p^.Bal = -1) THEN s^.Bal := 1; r^.Bal := 0; ELSIF (p^.Bal = 0) THEN s^.Bal := 0; r^.Bal := 0; ELSE s^.Bal := 0; r^.Bal := -1; END; p^.Bal := 0; END; ELSE (* a = +1. *) IF (s^.Bal = 0) THEN s^.Bal := 1; fertig := TRUE; ELSIF (s^.Bal = -1) THEN s^.Bal := 0; fertig := TRUE; ELSIF (r^.Bal = 1) THEN (* A8. *) p := r; s^.Link[1] := r^.Link[0]; r^.Link[0] := s; s^.Bal := 0; r^.Bal := 0; ELSE (* A9. *) p := r^.Link[0]; r^.Link[0] := p^.Link[1]; p^.Link[1] := r; s^.Link[1] := p^.Link[0]; p^.Link[0] := s; IF (p^.Bal = 1) THEN s^.Bal := -1; r^.Bal := 0; ELSIF (p^.Bal = 0) THEN s^.Bal := 0; r^.Bal := 0; ELSE s^.Bal := 0; r^.Bal := 1; END; p^.Bal := 0; END; END; (* A10. *) IF NOT fertig THEN (*if (t <> *tree && s = t^.Left)*) IF (s = t^.Link[1]) THEN t^.Link[1] := p; ELSIF (s = t^.Link[0]) THEN t^.Link[0] := p; ELSE tree := p; END; END; END; END AvlInsert; PROCEDURE AvlRemove(VAR tree : AvlBaum; Key : AvlKeyType); (* Uses my Algorithm D, which can be found at http://www.msu.edu/user/pfaffben/avl. Algorithm D is based on Knuth's Algorithm 6.2.2D (Tree deletion) and 6.2.3A (Balanced tree search and insertion), as well as the notes on pages 465-466 of Vol. 3. *) VAR (* D1. *) pa : ARRAY[0..AvlMaxHeight] OF AvlKnoten; (* Stack P: Nodes. *) a : ARRAY[0..AvlMaxHeight] OF INTEGER; (* Stack P: Bits. *) k : INTEGER; (* Stack P: Pointer. *) p, q, r, s : AvlKnoten; l : INTEGER; fertig : BOOLEAN; BEGIN (* insert dummy entry because access to k-1 is used *) (* and this can generate access to pa[0], but we dont *) (* want to modify any node in the tree *) a[0] := 0; Allocate(pa[0],TSIZE(AvlElement)); pa[0]^.Key := 0; pa[0]^.Link[0] := NIL; pa[0]^.Link[1] := NIL; p := tree; k := 1; fertig := FALSE; WHILE NOT fertig DO (* D2. *) IF (p = NIL) THEN fertig := TRUE; ELSIF (Key = p^.Key) THEN fertig := TRUE; ELSE (* D3, D4. *) pa[k] := p; IF (Key < p^.Key) THEN p := p^.Link[0]; a[k] := 0; ELSIF (Key > p^.Key) THEN p := p^.Link[1]; a[k] := 1; END; k := k + 1; END; END; IF p <> NIL THEN (* D5. *) IF (p^.Link[1] = NIL) THEN pa[k - 1]^.Link[a[k - 1]] := p^.Link[0]; IF (pa[k - 1]^.Link[a[k - 1]] <> NIL) THEN pa[k - 1]^.Link[a[k - 1]]^.Bal := 0; END; ELSE (* D6. *) r := p^.Link[1]; IF (r^.Link[0] = NIL) THEN r^.Link[0] := p^.Link[0]; q := r; r^.Bal := p^.Bal; a[k] := 1; pa[k] := r; k := k + 1; ELSE (* D7. *) s := r^.Link[0]; l := k; k := k + 1; a[k] := 0; pa[k] := r; k := k + 1; (* D8. *) WHILE (s^.Link[0] <> NIL) DO r := s; s := r^.Link[0]; a[k] := 0; pa[k] := r; k := k + 1; END; (* D9. *) a[l] := 1; pa[l] := s; s^.Link[0] := p^.Link[0]; r^.Link[0] := s^.Link[1]; s^.Link[1] := p^.Link[1]; s^.Bal := p^.Bal; q := s; END; END; IF (p = tree) THEN (* Michael Bernstein: delete tree, we had to set new tree *) tree := q; END; (* Michael Bernstein: else tree is unchanged *) Deallocate(p,TSIZE(AvlElement)); (* D10. *) k := k - 1; WHILE (k > 0) DO fertig := FALSE; s := pa[k]; IF (a[k] = 0) THEN (* D10. *) IF (s^.Bal = -1) THEN s^.Bal := 0; fertig := TRUE; ELSIF (s^.Bal = 0) THEN s^.Bal := 1; fertig := TRUE; k := 0; (* to end loop *) END; IF NOT fertig THEN r := s^.Link[1]; IF (r^.Bal = 0) THEN (* D11. *) s^.Link[1] := r^.Link[0]; r^.Link[0] := s; r^.Bal := -1; pa[k - 1]^.Link[a[k - 1]] := r; IF (tree = s) THEN (* Michael Bernstein: if k = 1 we have to set new root into tree *) tree := r; END; fertig := TRUE; k := 0; (* to end loop *) ELSIF (r^.Bal = 1) THEN (* D12. *) s^.Link[1] := r^.Link[0]; r^.Link[0] := s; s^.Bal := 0; r^.Bal := 0; pa[k - 1]^.Link[a[k - 1]] := r; IF (tree = s) THEN (* Michael Bernstein: if k = 1 we have to set new root into tree *) tree := r; END; ELSE (* D13. *) p := r^.Link[0]; r^.Link[0] := p^.Link[1]; p^.Link[1] := r; s^.Link[1] := p^.Link[0]; p^.Link[0] := s; IF (p^.Bal = 1) THEN s^.Bal := -1; r^.Bal := 0; ELSIF (p^.Bal = 0) THEN s^.Bal := 0; r^.Bal := 0; ELSE s^.Bal := 0; r^.Bal := 1; END; p^.Bal := 0; pa[k - 1]^.Link[a[k - 1]] := p; IF (tree = s) THEN (* Michael Bernstein: if k = 1 we have to set new root into tree *) tree := p; END; END; END; ELSE (* D10. *) IF (s^.Bal = 1) THEN s^.Bal := 0; fertig := TRUE; ELSIF (s^.Bal = 0) THEN s^.Bal := -1; fertig := TRUE; k := 0; (* to end loop *) END; IF NOT fertig THEN r := s^.Link[0]; IF (r^.Bal = 0) THEN (* D11. *) s^.Link[0] := r^.Link[1]; r^.Link[1] := s; r^.Bal := 1; pa[k - 1]^.Link[a[k - 1]] := r; IF (tree = s) THEN (* Michael Bernstein: if k = 1 we have to set new root into tree *) tree := r; END; fertig := TRUE; k := 0; (* to end loop *) ELSIF (r^.Bal = -1) THEN (* D12. *) s^.Link[0] := r^.Link[1]; r^.Link[1] := s; s^.Bal := 0; r^.Bal := 0; pa[k - 1]^.Link[a[k - 1]] := r; IF (tree = s) THEN (* Michael Bernstein: if k = 1 we have to set new root into tree *) tree := r; END; ELSIF (r^.Bal = 1) THEN (* D13. *) p := r^.Link[1]; r^.Link[1] := p^.Link[0]; p^.Link[0] := r; s^.Link[0] := p^.Link[1]; p^.Link[1] := s; IF (p^.Bal = -1) THEN s^.Bal := 1; r^.Bal := 0; ELSIF (p^.Bal = 0) THEN s^.Bal := 0; r^.Bal := 0; ELSE s^.Bal := 0; r^.Bal := -1; END; p^.Bal := 0; pa[k - 1]^.Link[a[k - 1]] := p; IF (tree = s) THEN (* Michael Bernstein: if k = 1 we have to set new root into tree *) tree := p; END; END; END; END; k := k - 1; END; END; Deallocate(pa[0],TSIZE(AvlElement)); END AvlRemove; PROCEDURE AvlFind(tree : AvlBaum; Key : AvlKeyType) : AvlKnoten; VAR PresentPtr : AvlKnoten; Found : BOOLEAN; BEGIN (* iterativ, schneller als rekursiv *) PresentPtr := tree; Found := FALSE; WHILE NOT Found DO IF (PresentPtr = NIL) THEN Found := TRUE; ELSIF (PresentPtr^.Key = Key) THEN Found := TRUE; ELSIF (Key < PresentPtr^.Key) THEN PresentPtr := PresentPtr^.Link[0] ELSIF (Key > PresentPtr^.Key) THEN PresentPtr := PresentPtr^.Link[1]; END; END; RETURN PresentPtr; END AvlFind;
English version not yet available. |