DoublyLinkedList.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /* DoublyLinkedList.cpp
  2. *
  3. * Copyright (C) 2011-2017 David Weenink
  4. *
  5. * This code is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or (at
  8. * your option) any later version.
  9. *
  10. * This code is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. * See the GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this work. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include "DoublyLinkedList.h"
  19. Thing_implement (DoublyLinkedNode, Daata, 0);
  20. void structDoublyLinkedNode :: v_destroy () noexcept {
  21. DoublyLinkedNode_Parent :: v_destroy ();
  22. }
  23. void structDoublyLinkedNode :: v_copy (Daata thee_Daata) {
  24. DoublyLinkedNode thee = static_cast <DoublyLinkedNode> (thee_Daata);
  25. thy data = Data_copy (our data.get());
  26. }
  27. Thing_implement (DoublyLinkedList, Thing, 0);
  28. void structDoublyLinkedList :: v_destroy () noexcept {
  29. DoublyLinkedNode v = front;
  30. while (v) {
  31. DoublyLinkedNode cur = v;
  32. v = v -> next;
  33. forget (cur);
  34. }
  35. DoublyLinkedList_Parent :: v_destroy ();
  36. }
  37. int structDoublyLinkedList :: s_compareHook (Daata /* node1 */, Daata /* node2 */) noexcept {
  38. return 0;
  39. }
  40. autoDoublyLinkedNode DoublyLinkedNode_create (autoDaata data) {
  41. autoDoublyLinkedNode me = Thing_new (DoublyLinkedNode);
  42. my data = data.move();
  43. return me;
  44. }
  45. void DoublyLinkedList_init (DoublyLinkedList) {
  46. }
  47. autoDoublyLinkedList DoublyLinkedList_create() {
  48. try {
  49. autoDoublyLinkedList me = Thing_new (DoublyLinkedList);
  50. DoublyLinkedList_init (me.get());
  51. return me;
  52. } catch (MelderError) {
  53. Melder_throw (U"DoublyLinkedList not created.");
  54. }
  55. }
  56. void DoublyLinkedList_addFront (DoublyLinkedList me, DoublyLinkedNode node) {
  57. if (my front) {
  58. DoublyLinkedList_addBefore (me, my front, node);
  59. } else { // empty list
  60. my front = node;
  61. my back = node;
  62. node -> next = nullptr;
  63. node -> prev = nullptr;
  64. my numberOfNodes ++;
  65. }
  66. }
  67. void DoublyLinkedList_addBack (DoublyLinkedList me, DoublyLinkedNode node) {
  68. if (my back) {
  69. DoublyLinkedList_addAfter (me, my back, node);
  70. } else {
  71. DoublyLinkedList_addFront (me, node); // empty list
  72. }
  73. }
  74. void DoublyLinkedList_addBefore (DoublyLinkedList me, DoublyLinkedNode pos, DoublyLinkedNode node) {
  75. node -> prev = pos -> prev;
  76. node -> next = pos;
  77. if (pos -> prev == nullptr) {
  78. my front = node;
  79. } else {
  80. pos -> prev -> next = node;
  81. }
  82. pos -> prev = node;
  83. my numberOfNodes ++;
  84. }
  85. void DoublyLinkedList_addAfter (DoublyLinkedList me, DoublyLinkedNode pos, DoublyLinkedNode node) {
  86. node -> prev = pos;
  87. node -> next = pos -> next;
  88. if (pos -> next == nullptr) {
  89. my back = node;
  90. } else {
  91. pos -> next -> prev = node;
  92. }
  93. pos -> next = node;
  94. my numberOfNodes ++;
  95. }
  96. void DoublyLinkedList_remove (DoublyLinkedList me, DoublyLinkedNode node) {
  97. if (my numberOfNodes == 0) {
  98. return;
  99. }
  100. if (node == my front) {
  101. my front = my front -> next;
  102. my front -> prev = nullptr;
  103. } else if (node == my back) {
  104. my back = my back -> prev;
  105. my back -> next = nullptr;
  106. } else {
  107. node -> prev -> next = node -> next;
  108. node -> next -> prev = node -> prev;
  109. }
  110. forget (node);
  111. my numberOfNodes --;
  112. }
  113. // Preconditions:
  114. // from and to should be part of the list
  115. // from must occur before to
  116. void DoublyLinkedList_sortPart (DoublyLinkedList me, DoublyLinkedNode from, DoublyLinkedNode to) {
  117. // Save data
  118. if (from == to) {
  119. return; // nothing to do
  120. }
  121. DoublyLinkedNode from_prev = from -> prev;
  122. DoublyLinkedNode to_next = to -> next;
  123. DoublyLinkedNode my_front = my front;
  124. DoublyLinkedNode my_back = my back;
  125. from -> prev = to -> next = nullptr;
  126. my front = from;
  127. my back = to;
  128. DoublyLinkedList_sort (me);
  129. // restore complete list
  130. my front -> prev = from_prev;
  131. if (from_prev) {
  132. from_prev -> next = my front;
  133. }
  134. my back -> next = to_next;
  135. if (to_next) {
  136. to_next -> prev = my back;
  137. }
  138. if (my_front != from) {
  139. my front = my_front;
  140. }
  141. if (my_back != to) {
  142. my back = my_back;
  143. }
  144. }
  145. void DoublyLinkedList_sort (DoublyLinkedList me) {
  146. Data_CompareHook::FunctionType compare = my v_getCompareHook ().get();
  147. integer increment = 1;
  148. DoublyLinkedNode front = my front, back;
  149. for (;;) {
  150. DoublyLinkedNode node1 = front;
  151. front = nullptr;
  152. back = nullptr;
  153. integer numberOfMerges = 0;
  154. while (node1) {
  155. DoublyLinkedNode node2 = node1, node;
  156. integer node1size = 0;
  157. numberOfMerges++;
  158. for (integer i = 1; i <= increment; i++) {
  159. node1size++;
  160. node2 = node2 -> next;
  161. if (! node2) {
  162. break;
  163. }
  164. }
  165. integer node2size = increment;
  166. while (node1size > 0 || (node2size > 0 && node2)) { // merge node1 and node2
  167. if (node1size == 0) {
  168. node2size--; node = node2; node2 = node2 -> next;
  169. } else if (node2size == 0 || ! node2) {
  170. node1size--; node = node1; node1 = node1 -> next;
  171. } else if (compare (node1, node2) <= 0) {
  172. node1size--; node = node1; node1 = node1 -> next;
  173. } else {
  174. node2size--; node = node2; node2 = node2 -> next;
  175. }
  176. if (back) {
  177. back -> next = node;
  178. } else {
  179. front = node;
  180. }
  181. node -> prev = back;
  182. back = node;
  183. }
  184. node1 = node2;
  185. }
  186. back -> next = nullptr;
  187. if (numberOfMerges <= 1) {
  188. break;
  189. }
  190. increment *= 2;
  191. }
  192. //
  193. my front = front;
  194. my back = back;
  195. }
  196. /* end of file DoublyLinkedList.cpp */