| ... | ... | @@ -123,76 +123,9 @@ pub fn SinglyLinkedList(comptime T: type) type { |
| 123 | 123 | return 0; |
| 124 | 124 | } |
| 125 | 125 | } |
| 126 | | |
| 127 | | /// Performs a stable in-place merge sort on the entire list. |
| 128 | | /// This operation is O(N log N) with O(1) memory (no allocator required). |
| 129 | | /// Sorts in ascending order with respect to the given `lessThan` function. |
| 130 | | /// Arguments: |
| 131 | | /// lessThanFn: Comparison function for the data of two nodes. |
| 132 | | pub fn sort( |
| 133 | | list: *Self, |
| 134 | | comptime lessThanFn: fn (left: Node.Data, right: Node.Data) bool, |
| 135 | | ) void { |
| 136 | | list.first = mergeSort(list.first, lessThanFn); |
| 137 | | } |
| 138 | | |
| 139 | | /// Performs a stable in-place merge sort on the given node and its descendants. |
| 140 | | /// This operation is O(N log N) with O(1) memory (no allocator required). |
| 141 | | /// Sorts in ascending order with respect to the given `lessThan` function. |
| 142 | | /// Arguments: |
| 143 | | /// node: Pointer to the first node of the list to sort. |
| 144 | | /// lessThanFn: Comparison function for the data of two nodes. |
| 145 | | /// Returns: |
| 146 | | /// A pointer to the first node of the sorted list. |
| 147 | | pub fn mergeSort( |
| 148 | | node: ?*Node, |
| 149 | | comptime lessThanFn: fn (left: Node.Data, right: Node.Data) bool, |
| 150 | | ) ?*Node { |
| 151 | | if (node == null or node.?.next == null) return node; |
| 152 | | |
| 153 | | // find middle of list |
| 154 | | var slow = node; |
| 155 | | var fast = node; |
| 156 | | |
| 157 | | while (fast.?.next != null and fast.?.next.?.next != null) { |
| 158 | | slow = slow.?.next; |
| 159 | | fast = fast.?.next.?.next; |
| 160 | | } |
| 161 | | |
| 162 | | // split list in half |
| 163 | | const half = slow.?.next; |
| 164 | | slow.?.next = null; |
| 165 | | |
| 166 | | // sort both halfs |
| 167 | | const left = mergeSort(node, lessThanFn); |
| 168 | | const right = mergeSort(half, lessThanFn); |
| 169 | | |
| 170 | | // merge sorted halfs |
| 171 | | return merge(left, right, lessThanFn); |
| 172 | | } |
| 173 | | fn merge( |
| 174 | | left: ?*Node, |
| 175 | | right: ?*Node, |
| 176 | | comptime lessThanFn: fn (left: Node.Data, right: Node.Data) bool, |
| 177 | | ) ?*Node { |
| 178 | | var left_ptr = left orelse return right; |
| 179 | | var right_ptr = right orelse return left; |
| 180 | | |
| 181 | | if (lessThanFn(left_ptr.data, right_ptr.data)) { |
| 182 | | left_ptr.next = merge(left_ptr.next, right_ptr, lessThanFn); |
| 183 | | return left_ptr; |
| 184 | | } else { |
| 185 | | right_ptr.next = merge(left_ptr, right_ptr.next, lessThanFn); |
| 186 | | return right_ptr; |
| 187 | | } |
| 188 | | } |
| 189 | 126 | }; |
| 190 | 127 | } |
| 191 | 128 | |
| 192 | | fn testLessThan(left: u32, right: u32) bool { |
| 193 | | return left < right; |
| 194 | | } |
| 195 | | |
| 196 | 129 | test "basic SinglyLinkedList test" { |
| 197 | 130 | const L = SinglyLinkedList(u32); |
| 198 | 131 | var list = L{}; |
| ... | ... | @@ -236,22 +169,6 @@ test "basic SinglyLinkedList test" { |
| 236 | 169 | try testing.expect(list.first.?.data == 4); |
| 237 | 170 | try testing.expect(list.first.?.next.?.data == 2); |
| 238 | 171 | try testing.expect(list.first.?.next.?.next == null); |
| 239 | | |
| 240 | | list.prepend(&five); // {5, 4, 2} |
| 241 | | list.prepend(&one); // {1, 5, 4, 2} |
| 242 | | list.prepend(&three); // {3, 1, 5, 4, 2} |
| 243 | | |
| 244 | | list.sort(testLessThan); |
| 245 | | |
| 246 | | // Traverse forwards. |
| 247 | | { |
| 248 | | var it = list.first; |
| 249 | | var index: u32 = 1; |
| 250 | | while (it) |node| : (it = node.next) { |
| 251 | | try testing.expect(node.data == index); |
| 252 | | index += 1; |
| 253 | | } |
| 254 | | } |
| 255 | 172 | } |
| 256 | 173 | |
| 257 | 174 | /// A doubly-linked list has a pair of pointers to both the head and |