2019-09-09 10:22:36 +10:00
|
|
|
/*
|
|
|
|
* 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 <danny@nerdcruft.net>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "../debug/assert.hpp"
|
|
|
|
|
|
|
|
#include <iterator>
|
|
|
|
#include <utility>
|
|
|
|
|
|
|
|
namespace cruft::list {
|
2019-09-09 10:24:28 +10:00
|
|
|
/// A simple tuple-style linked list node.
|
2019-09-09 10:22:36 +10:00
|
|
|
template <typename ValueT>
|
|
|
|
struct node {
|
|
|
|
node *next;
|
|
|
|
ValueT data;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template <typename ValueT>
|
|
|
|
node<ValueT>*
|
|
|
|
midpoint (node<ValueT> *first, node<ValueT> *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 <typename ValueT>
|
|
|
|
node<ValueT>*
|
|
|
|
merge (
|
|
|
|
node<ValueT> *first,
|
|
|
|
node<ValueT> *middle,
|
|
|
|
node<ValueT> *last
|
|
|
|
) {
|
|
|
|
CHECK (first);
|
|
|
|
CHECK (middle);
|
|
|
|
CHECK (last);
|
|
|
|
|
|
|
|
if (first == last)
|
|
|
|
return first;
|
|
|
|
|
|
|
|
auto extract = [&] () {
|
2019-09-09 10:24:28 +10:00
|
|
|
auto &target = first->data < middle->data ? first : middle;
|
2019-09-09 10:22:36 +10:00
|
|
|
auto res = target;
|
|
|
|
target = target->next;
|
|
|
|
return res;
|
|
|
|
};
|
|
|
|
|
|
|
|
node<ValueT> *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 <typename ValueT>
|
|
|
|
node<ValueT>*
|
|
|
|
sort (node<ValueT> *first, node<ValueT> *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 <typename ValueT>
|
|
|
|
bool is_sorted (node<ValueT> const *head)
|
|
|
|
{
|
|
|
|
if (!head->next)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
auto a = head;
|
|
|
|
auto b = head->next;
|
|
|
|
|
|
|
|
while (b) {
|
2019-09-09 10:24:28 +10:00
|
|
|
if (b->data < a->data)
|
2019-09-09 10:22:36 +10:00
|
|
|
return false;
|
|
|
|
|
|
|
|
a = a->next;
|
|
|
|
b = b->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|