LISTS.ob07 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. (*
  2. BSD 2-Clause License
  3. Copyright (c) 2018-2021, Anton Krotov
  4. All rights reserved.
  5. *)
  6. MODULE LISTS;
  7. IMPORT C := COLLECTIONS;
  8. TYPE
  9. ITEM* = POINTER TO RECORD (C.ITEM)
  10. prev*, next*: ITEM
  11. END;
  12. LIST* = POINTER TO RECORD
  13. first*, last*: ITEM
  14. END;
  15. PROCEDURE push* (list: LIST; item: ITEM);
  16. BEGIN
  17. ASSERT(list # NIL);
  18. ASSERT(item # NIL);
  19. IF list.first = NIL THEN
  20. list.first := item;
  21. item.prev := NIL
  22. ELSE
  23. ASSERT(list.last # NIL);
  24. item.prev := list.last;
  25. list.last.next := item
  26. END;
  27. list.last := item;
  28. item.next := NIL
  29. END push;
  30. PROCEDURE pop* (list: LIST): ITEM;
  31. VAR
  32. last: ITEM;
  33. BEGIN
  34. ASSERT(list # NIL);
  35. last := list.last;
  36. IF last # NIL THEN
  37. IF last = list.first THEN
  38. list.first := NIL;
  39. list.last := NIL
  40. ELSE
  41. list.last := last.prev;
  42. list.last.next := NIL
  43. END;
  44. last.next := NIL;
  45. last.prev := NIL
  46. END
  47. RETURN last
  48. END pop;
  49. PROCEDURE insert* (list: LIST; cur, nov: ITEM);
  50. VAR
  51. next: ITEM;
  52. BEGIN
  53. ASSERT(list # NIL);
  54. ASSERT(nov # NIL);
  55. ASSERT(cur # NIL);
  56. next := cur.next;
  57. IF next # NIL THEN
  58. next.prev := nov;
  59. nov.next := next;
  60. cur.next := nov;
  61. nov.prev := cur
  62. ELSE
  63. push(list, nov)
  64. END
  65. END insert;
  66. PROCEDURE insertL* (list: LIST; cur, nov: ITEM);
  67. VAR
  68. prev: ITEM;
  69. BEGIN
  70. ASSERT(list # NIL);
  71. ASSERT(nov # NIL);
  72. ASSERT(cur # NIL);
  73. prev := cur.prev;
  74. IF prev # NIL THEN
  75. prev.next := nov;
  76. nov.prev := prev
  77. ELSE
  78. nov.prev := NIL;
  79. list.first := nov
  80. END;
  81. cur.prev := nov;
  82. nov.next := cur
  83. END insertL;
  84. PROCEDURE delete* (list: LIST; item: ITEM);
  85. VAR
  86. prev, next: ITEM;
  87. BEGIN
  88. ASSERT(list # NIL);
  89. ASSERT(item # NIL);
  90. prev := item.prev;
  91. next := item.next;
  92. IF next # NIL THEN
  93. IF prev # NIL THEN
  94. prev.next := next;
  95. next.prev := prev
  96. ELSE
  97. next.prev := NIL;
  98. list.first := next
  99. END
  100. ELSE
  101. IF prev # NIL THEN
  102. prev.next := NIL;
  103. list.last := prev
  104. ELSE
  105. list.first := NIL;
  106. list.last := NIL
  107. END
  108. END
  109. END delete;
  110. PROCEDURE count* (list: LIST): INTEGER;
  111. VAR
  112. item: ITEM;
  113. res: INTEGER;
  114. BEGIN
  115. ASSERT(list # NIL);
  116. res := 0;
  117. item := list.first;
  118. WHILE item # NIL DO
  119. INC(res);
  120. item := item.next
  121. END
  122. RETURN res
  123. END count;
  124. PROCEDURE getidx* (list: LIST; idx: INTEGER): ITEM;
  125. VAR
  126. item: ITEM;
  127. BEGIN
  128. ASSERT(list # NIL);
  129. ASSERT(idx >= 0);
  130. item := list.first;
  131. WHILE (item # NIL) & (idx > 0) DO
  132. item := item.next;
  133. DEC(idx)
  134. END
  135. RETURN item
  136. END getidx;
  137. PROCEDURE create* (list: LIST): LIST;
  138. BEGIN
  139. IF list = NIL THEN
  140. NEW(list)
  141. END;
  142. list.first := NIL;
  143. list.last := NIL
  144. RETURN list
  145. END create;
  146. END LISTS.