home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Programming / Misc / OB3.2D2.DMS / in.adf / Module / BinaryTrees.mod < prev    next >
Encoding:
Text File  |  1994-08-05  |  5.1 KB  |  285 lines

  1. (*-------------------------------------------------------------------------*)
  2. (*                                                                         *)
  3. (*  Amiga Oberon Library Module: BinaryTrees          Date: 02-Nov-92      *)
  4. (*                                                                         *)
  5. (*   © 1992 by Fridtjof Siebert                                            *)
  6. (*                                                                         *)
  7. (*-------------------------------------------------------------------------*)
  8.  
  9. MODULE BinaryTrees;
  10.  
  11. IMPORT BT * := BasicTypes;
  12.  
  13. TYPE
  14.  
  15.   Node * = POINTER TO NodeDesc;
  16.   NodeDesc * = RECORD (BT.COMPAREABLEDesc)
  17.     l * : Node;
  18.     r * : Node;
  19.   END;
  20.  
  21.  
  22.   Root * = POINTER TO RootDesc;
  23.   RootDesc * = RECORD (BT.COLLECTIONDesc)
  24.     root  * : Node;
  25.     addOk * : BOOLEAN;
  26.     remOk * : BOOLEAN;
  27.   END;
  28.  
  29.  
  30. PROCEDURE (a: Node) Find*(root: Root): LONGINT;
  31. (* Diese Prozedur wird von Find() verwendet.
  32.  *  Ihr Ergebnis ist
  33.  *    = 0, wenn a das gesuchte Element ist
  34.  *    < 0, wenn a < dem gesuchten Element ist
  35.  *    > 0, wenn a > dem gesuchten Element ist
  36.  *)
  37. BEGIN HALT(20) END Find;
  38.  
  39.  
  40. (*-------------------------------------------------------------------------*)
  41.  
  42.  
  43. (*------  Create:  ------*)
  44.  
  45.  
  46. PROCEDURE Create*(): Root;
  47. (*
  48.  * alloziert neuen, leeren AVL-Baum
  49.  *)
  50.  
  51. VAR
  52.   r: Root;
  53.  
  54. BEGIN
  55.   NEW(r); RETURN r;
  56. END Create;
  57.  
  58.  
  59. (*------  Add:  ------*)
  60.  
  61.  
  62. PROCEDURE (root: Root) Add* (node: BT.ANY);
  63.  
  64. (* fügt node in den Baum ein.
  65.  * War ein gleichnamiger Knoten bereits im Baum, wird der Baum nicht
  66.  * verändert und roo.addOk auf FALSE gesetzt.
  67.  *
  68.  * require
  69.  *   node IS Node
  70.  *
  71.  *)
  72.  
  73.   PROCEDURE Search(VAR n: Node);
  74.  
  75.   VAR c: LONGINT;
  76.  
  77.   BEGIN
  78.     IF n=NIL THEN                       (* neues Element einfügen: *)
  79.       n := node(Node);
  80.       n.l := NIL; n.r := NIL; 
  81.       root.addOk := TRUE;
  82.     ELSE
  83.       c := n.Compare(node(Node));
  84.       IF c>0 THEN
  85.         Search(n.l);
  86.       ELSIF c<0 THEN
  87.         Search(n.r);
  88.       END;
  89.     END;
  90.   END Search;
  91.  
  92. BEGIN
  93.   root.addOk := FALSE;
  94.   Search(root.root);
  95. END Add;
  96.  
  97.  
  98. (*------  Find:  ------*)
  99.  
  100.  
  101. PROCEDURE (root: Root) Find* (): Node;
  102.  
  103. (* Sucht denjenigen Knoten, für den Root.Find das Ergebnis 0 liefert und
  104.    gibt seine Adresse oder NIL zurück. *)
  105.  
  106. VAR
  107.   n: Node;
  108.   c: LONGINT;
  109.  
  110. BEGIN
  111.   n := root.root;
  112.   LOOP
  113.     IF n=NIL THEN RETURN NIL END;
  114.     c := n.Find(root);
  115.     IF    c<0 THEN n := n.r
  116.     ELSIF c>0 THEN n := n.l
  117.               ELSE RETURN n END;
  118.   END;
  119. END Find;
  120.  
  121.  
  122. (*------  Remove:  ------*)
  123.  
  124.  
  125. PROCEDURE (root: Root) Remove* (node: BT.ANY);
  126.  
  127. (* Entfernt node aus dem Baum. 
  128.  * War node nicht im Baum, wird der Baum nicht verändert und roo.remOk auf FALSE 
  129.  * gesetzt.
  130.  *
  131.  * require
  132.  *   node IS Node
  133.  *)
  134.  
  135.   PROCEDURE Rem(VAR n: Node);
  136.  
  137.   VAR
  138.     c: LONGINT;
  139.     New,Q: Node;
  140.  
  141.   BEGIN
  142.     IF n # NIL THEN
  143.       c := n.Compare(node(Node));
  144.       IF    c>0 THEN Rem(n.l) 
  145.       ELSIF c<0 THEN Rem(n.r)
  146.       ELSE
  147.         root.remOk := TRUE;
  148.         IF    n.r=NIL THEN n := n.l 
  149.         ELSIF n.l=NIL THEN n := n.r 
  150.         ELSE
  151.           Q := n.l;  
  152.           WHILE Q.r#NIL DO Q := Q.r END;  
  153.           Q.r := n.r;  
  154.           n := n.l;  
  155.         END;
  156.       END;
  157.     END;
  158.   END Rem;
  159.  
  160. BEGIN
  161.   root.remOk := FALSE;
  162.   Rem(root.root); 
  163. END Remove;
  164.  
  165.  
  166. (*-------------------------------------------------------------------------*)
  167.  
  168.  
  169. PROCEDURE (tree: Root) nbElements * (): LONGINT;
  170. (* returns the number of elements within tree.
  171.  *)
  172.  
  173.   PROCEDURE CountElements(n: Node): LONGINT;
  174.   BEGIN
  175.     IF n=NIL THEN RETURN 0
  176.              ELSE RETURN CountElements(n.l) + CountElements(n.r) + 1
  177.     END;
  178.   END CountElements;
  179.  
  180. BEGIN
  181.   RETURN CountElements(tree.root);
  182. END nbElements;
  183.  
  184.  
  185. PROCEDURE (tree: Root) isEmpty * (): BOOLEAN;
  186. (* TRUE if tree is empty 
  187.  *)
  188.  
  189. BEGIN
  190.   RETURN tree.root=NIL;
  191. END isEmpty;
  192.  
  193.  
  194. PROCEDURE (tree: Root) Do         * (p: BT.DoProc; par: BT.ANY);
  195. (* calls p(x,par) for every element x stored within tree.
  196.  * the tree is travesed in infix order.
  197.  * par passes some additional information to p. par is not touched by Do.
  198.  *)
  199.  
  200.   PROCEDURE do(n: Node);
  201.  
  202.   BEGIN
  203.     IF n#NIL THEN
  204.       do(n.l);
  205.       p(n,par);
  206.       do(n.r);
  207.     END;
  208.   END do;
  209.  
  210. BEGIN
  211.   do(tree.root); 
  212. END Do;
  213.  
  214.  
  215. (*------  DoBackward:  ------*)
  216.  
  217.  
  218. PROCEDURE (root: Root) DoBackward* (proc: BT.DoProc; par: BT.ANY);
  219.  
  220. (* calls p(x,par) for every element x stored within tree.
  221.  * the tree is travesed in reverse order.
  222.  * par passes some additional information to p. par is not touched by Do.
  223.  *)
  224.  
  225.   PROCEDURE DoBkwd(n: Node);
  226.  
  227.   BEGIN
  228.     IF n#NIL THEN
  229.       DoBkwd(n.r);
  230.       proc(n,par);
  231.       DoBkwd(n.l);
  232.     END;
  233.   END DoBkwd;
  234.  
  235. BEGIN
  236.   DoBkwd(root.root);
  237. END DoBackward;
  238.  
  239.  
  240. (*------  Dispose:  ------*)
  241.  
  242.  
  243. PROCEDURE (root: Root) Dispose*;
  244.  
  245. (* Ruft DISPOSE() mit allen Elementen des Baumes auf, gibt also seinen
  246.  * gesamten Speicher frei.
  247.  *)
  248.  
  249. (* $IFNOT GarbageCollector *)
  250.  
  251.   PROCEDURE Disp(n: Node);
  252.  
  253.   BEGIN
  254.     IF n#NIL THEN
  255.       Disp(n.l);
  256.       Disp(n.r);
  257.       DISPOSE(n);
  258.     END;
  259.   END Disp;
  260.  
  261. (* $END *)
  262.  
  263. BEGIN
  264.  
  265. (* $IFNOT GarbageCollector *)
  266.  
  267.   Disp(root.root);
  268.  
  269. (* $ELSE *)
  270.  
  271.   root.root := NIL;
  272.  
  273. (* $END *)
  274.  
  275. END Dispose;
  276.  
  277.  
  278. (*-------------------------------------------------------------------------*)
  279.  
  280.  
  281. END BinaryTrees.
  282.  
  283.  
  284.  
  285.