| ... | @@ -123,76 +123,9 @@ pub fn SinglyLinkedList(comptime T: type) type { | ... | @@ -123,76 +123,9 @@ pub fn SinglyLinkedList(comptime T: type) type { |
| 123 | return 0; | 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 | test "basic SinglyLinkedList test" { | 129 | test "basic SinglyLinkedList test" { |
| 197 | const L = SinglyLinkedList(u32); | 130 | const L = SinglyLinkedList(u32); |
| 198 | var list = L{}; | 131 | var list = L{}; |
| ... | @@ -236,22 +169,6 @@ test "basic SinglyLinkedList test" { | ... | @@ -236,22 +169,6 @@ test "basic SinglyLinkedList test" { |
| 236 | try testing.expect(list.first.?.data == 4); | 169 | try testing.expect(list.first.?.data == 4); |
| 237 | try testing.expect(list.first.?.next.?.data == 2); | 170 | try testing.expect(list.first.?.next.?.data == 2); |
| 238 | try testing.expect(list.first.?.next.?.next == null); | 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 | /// A doubly-linked list has a pair of pointers to both the head and | 174 | /// A doubly-linked list has a pair of pointers to both the head and |