AVLTREES.ob07 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. (*
  2. BSD 2-Clause License
  3. Copyright (c) 2018-2019, Anton Krotov
  4. All rights reserved.
  5. *)
  6. MODULE AVLTREES;
  7. IMPORT C := COLLECTIONS;
  8. TYPE
  9. DATA* = POINTER TO RECORD (C.ITEM) END;
  10. NODE* = POINTER TO RECORD (C.ITEM)
  11. data*: DATA;
  12. height: INTEGER;
  13. left*, right*: NODE
  14. END;
  15. CMP* = PROCEDURE (a, b: DATA): INTEGER;
  16. DESTRUCTOR* = PROCEDURE (VAR data: DATA);
  17. VAR
  18. nodes: C.COLLECTION;
  19. PROCEDURE NewNode (data: DATA): NODE;
  20. VAR
  21. node: NODE;
  22. citem: C.ITEM;
  23. BEGIN
  24. citem := C.pop(nodes);
  25. IF citem = NIL THEN
  26. NEW(node)
  27. ELSE
  28. node := citem(NODE)
  29. END;
  30. node.data := data;
  31. node.left := NIL;
  32. node.right := NIL;
  33. node.height := 1
  34. RETURN node
  35. END NewNode;
  36. PROCEDURE height (p: NODE): INTEGER;
  37. VAR
  38. res: INTEGER;
  39. BEGIN
  40. IF p = NIL THEN
  41. res := 0
  42. ELSE
  43. res := p.height
  44. END
  45. RETURN res
  46. END height;
  47. PROCEDURE bfactor (p: NODE): INTEGER;
  48. RETURN height(p.right) - height(p.left)
  49. END bfactor;
  50. PROCEDURE fixheight (p: NODE);
  51. BEGIN
  52. p.height := MAX(height(p.left), height(p.right)) + 1
  53. END fixheight;
  54. PROCEDURE rotateright (p: NODE): NODE;
  55. VAR
  56. q: NODE;
  57. BEGIN
  58. q := p.left;
  59. p.left := q.right;
  60. q.right := p;
  61. fixheight(p);
  62. fixheight(q)
  63. RETURN q
  64. END rotateright;
  65. PROCEDURE rotateleft (q: NODE): NODE;
  66. VAR
  67. p: NODE;
  68. BEGIN
  69. p := q.right;
  70. q.right := p.left;
  71. p.left := q;
  72. fixheight(q);
  73. fixheight(p)
  74. RETURN p
  75. END rotateleft;
  76. PROCEDURE balance (p: NODE): NODE;
  77. VAR
  78. res: NODE;
  79. BEGIN
  80. fixheight(p);
  81. IF bfactor(p) = 2 THEN
  82. IF bfactor(p.right) < 0 THEN
  83. p.right := rotateright(p.right)
  84. END;
  85. res := rotateleft(p)
  86. ELSIF bfactor(p) = -2 THEN
  87. IF bfactor(p.left) > 0 THEN
  88. p.left := rotateleft(p.left)
  89. END;
  90. res := rotateright(p)
  91. ELSE
  92. res := p
  93. END
  94. RETURN res
  95. END balance;
  96. PROCEDURE insert* (p: NODE; data: DATA; cmp: CMP; VAR newnode: BOOLEAN; VAR node: NODE): NODE;
  97. VAR
  98. res: NODE;
  99. rescmp: INTEGER;
  100. BEGIN
  101. IF p = NIL THEN
  102. res := NewNode(data);
  103. node := res;
  104. newnode := TRUE
  105. ELSE
  106. rescmp := cmp(data, p.data);
  107. IF rescmp < 0 THEN
  108. p.left := insert(p.left, data, cmp, newnode, node);
  109. res := balance(p)
  110. ELSIF rescmp > 0 THEN
  111. p.right := insert(p.right, data, cmp, newnode, node);
  112. res := balance(p)
  113. ELSE
  114. res := p;
  115. node := res;
  116. newnode := FALSE
  117. END
  118. END
  119. RETURN res
  120. END insert;
  121. PROCEDURE destroy* (VAR node: NODE; destructor: DESTRUCTOR);
  122. VAR
  123. left, right: NODE;
  124. BEGIN
  125. IF node # NIL THEN
  126. left := node.left;
  127. right := node.right;
  128. IF destructor # NIL THEN
  129. destructor(node.data)
  130. END;
  131. C.push(nodes, node);
  132. node := NIL;
  133. destroy(left, destructor);
  134. destroy(right, destructor)
  135. END
  136. END destroy;
  137. BEGIN
  138. nodes := C.create()
  139. END AVLTREES.