Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 7596 → Rev 7597

/programs/develop/oberon07/Source/AVLTREES.ob07
0,0 → 1,197
(*
BSD 2-Clause License
 
Copyright (c) 2018, Anton Krotov
All rights reserved.
*)
 
MODULE AVLTREES;
 
IMPORT C := COLLECTIONS;
 
 
TYPE
 
DATA* = POINTER TO RECORD (C.ITEM) END;
 
NODE* = POINTER TO RECORD (C.ITEM)
 
data*: DATA;
 
height: INTEGER;
 
left*, right*: NODE
 
END;
 
CMP* = PROCEDURE (a, b: DATA): INTEGER;
 
DESTRUCTOR* = PROCEDURE (VAR data: DATA);
 
 
VAR
 
nodes: C.COLLECTION;
 
 
PROCEDURE NewNode (data: DATA): NODE;
VAR
node: NODE;
citem: C.ITEM;
 
BEGIN
citem := C.pop(nodes);
IF citem = NIL THEN
NEW(node)
ELSE
node := citem(NODE)
END;
 
node.data := data;
node.left := NIL;
node.right := NIL;
node.height := 1
 
RETURN node
END NewNode;
 
 
PROCEDURE height (p: NODE): INTEGER;
VAR
res: INTEGER;
 
BEGIN
IF p = NIL THEN
res := 0
ELSE
res := p.height
END
 
RETURN res
END height;
 
 
PROCEDURE bfactor (p: NODE): INTEGER;
RETURN height(p.right) - height(p.left)
END bfactor;
 
 
PROCEDURE fixheight (p: NODE);
BEGIN
p.height := MAX(height(p.left), height(p.right)) + 1
END fixheight;
 
 
PROCEDURE rotateright (p: NODE): NODE;
VAR
q: NODE;
 
BEGIN
q := p.left;
p.left := q.right;
q.right := p;
fixheight(p);
fixheight(q)
 
RETURN q
END rotateright;
 
 
PROCEDURE rotateleft (q: NODE): NODE;
VAR
p: NODE;
 
BEGIN
p := q.right;
q.right := p.left;
p.left := q;
fixheight(q);
fixheight(p)
 
RETURN p
END rotateleft;
 
 
PROCEDURE balance (p: NODE): NODE;
VAR
res: NODE;
 
BEGIN
fixheight(p);
 
IF bfactor(p) = 2 THEN
IF bfactor(p.right) < 0 THEN
p.right := rotateright(p.right)
END;
res := rotateleft(p)
 
ELSIF bfactor(p) = -2 THEN
IF bfactor(p.left) > 0 THEN
p.left := rotateleft(p.left)
END;
res := rotateright(p)
 
ELSE
res := p
END
 
RETURN res
END balance;
 
 
PROCEDURE insert* (p: NODE; data: DATA; cmp: CMP; VAR newnode: BOOLEAN; VAR node: NODE): NODE;
VAR
res: NODE;
rescmp: INTEGER;
 
BEGIN
IF p = NIL THEN
res := NewNode(data);
node := res;
newnode := TRUE
ELSE
 
rescmp := cmp(data, p.data);
IF rescmp < 0 THEN
p.left := insert(p.left, data, cmp, newnode, node);
res := balance(p)
ELSIF rescmp > 0 THEN
p.right := insert(p.right, data, cmp, newnode, node);
res := balance(p)
ELSE
res := p;
node := res;
newnode := FALSE
END
 
END
 
RETURN res
END insert;
 
 
PROCEDURE destroy* (VAR node: NODE; destructor: DESTRUCTOR);
VAR
left, right: NODE;
 
BEGIN
IF node # NIL THEN
left := node.left;
right := node.right;
 
IF destructor # NIL THEN
destructor(node.data)
END;
C.push(nodes, node);
node := NIL;
 
destroy(left, destructor);
destroy(right, destructor)
END
END destroy;
 
 
BEGIN
nodes := C.create()
END AVLTREES.