From d3e9444cbae6167952644b91029e35fe1f2ce051 Mon Sep 17 00:00:00 2001 From: Gregory Lirent Date: Sat, 4 Jun 2022 21:59:33 +0300 Subject: [PATCH] Add list sort --- src/list/sort.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 src/list/sort.c diff --git a/src/list/sort.c b/src/list/sort.c new file mode 100644 index 0000000..b4623d9 --- /dev/null +++ b/src/list/sort.c @@ -0,0 +1,104 @@ +/* This software is licensed by the MIT License, see LICENSE file */ +/* Copyright © 2022 Gregory Lirent */ + +#include "include.h" + +/*#####################################################################################################################*/ + +static inline void lnode_swap(lnode_t* s0, lnode_t* s1) { + vnode_t v = s0->node; + vtype t = s0->type; + + s0->node = s1->node; + s0->type = s1->type; + + s1->node = v; + s1->type = t; +} + +static inline lnode_t* mid(lnode_t* l, lnode_t *r) { + while (l != r) { + if ((r = r->prev) == l) + break; + l = l->next; + } + + return l; +} + +static inline lnode_t* pivot(lnode_t *l, lnode_t *r) { + + lnode_t *m = mid(l, r); + + if (lnode_compare(m, l) < 0) + lnode_swap(m, l); + + if (lnode_compare(m, r) > 0) { + lnode_swap(m, r); + + if (lnode_compare(m, l) < 0) + lnode_swap(m, l); + } + + return m; +} + +/*#####################################################################################################################*/ + +static void quick_sort(lnode_t *l, lnode_t *r) { + + lnode_t *c; + lnode_t *m = pivot(l, r); + lnode_t *n = l; + lnode_t *p = r; + int f = 0; + + for (;;) { + while (lnode_compare(l, m) < 0) { + l = l->next; + if (p == l) /* l >= p */ + f |= 0x01; + } + + c = l->prev; + + while (lnode_compare(r, m) > 0) { + r = r->prev; + if (n == r) /* n >= r */ + f |= 0x02; + if (c == r) /* l > r */ + f |= 0x04; + } + + if (!(f&0x04)) { /* l <= r */ + lnode_swap(l, r); + l = l->next; + r = r->prev;; + } else break; + } + + if (!(f&0x02)) /* n < r */ + quick_sort(n, r); + if (!(f&0x01)) /* l < p */ + quick_sort(l, p); +} + +/*#####################################################################################################################*/ + +void list_sort(list_t* x) { + if (x->first != x->last) + return quick_sort(x->first, x->last);; +} + + +void list_reverse(list_t* x) { + lnode_t *l = x->first; + lnode_t *r = x->last; + + while (l != r) { + lnode_swap(l, r); + if ((r = r->prev) == l) + break; + l = l->next; + } +}