/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Copyright 2019 Danny Robson */ #pragma once #include "../debug/assert.hpp" #include #include namespace cruft::list { template struct node { node *next; ValueT data; bool operator< (node const &rhs) const { return data < rhs.data; } }; template node* midpoint (node *first, node *last) { auto slow = first; auto fast = first->next; while (fast != last->next) { fast = fast->next; if (fast == last->next) return slow; fast = fast->next; slow = slow->next; } return slow; } template node* merge ( node *first, node *middle, node *last ) { CHECK (first); CHECK (middle); CHECK (last); if (first == last) return first; auto extract = [&] () { auto &target = *first < *middle ? first : middle; auto res = target; target = target->next; return res; }; node *cursor = extract (); auto head = cursor; while (first && middle && first != middle && middle != last->next) { auto target = extract (); cursor->next = target; cursor = target; } if (first == middle || !first) cursor->next = middle; else if (middle == last->next || !middle) cursor->next = first; return head; } // Merge sort for singly-linked lists template node* sort (node *first, node *last) { if (first == last) return first; auto a_end = ::cruft::list::midpoint (first, last); auto middle = a_end->next; a_end->next = nullptr; auto a = ::cruft::list::sort (first, a_end); auto b = ::cruft::list::sort (middle, last); return ::cruft::list::merge (a, b, last); } template bool is_sorted (node const *head) { if (!head->next) return true; auto a = head; auto b = head->next; while (b) { if (*b < *a) return false; a = a->next; b = b->next; } return true; } }