AVLTREES.ob07 3.5 KB

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