|
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. |