Add list sort
This commit is contained in:
parent
9bd9440a49
commit
d3e9444cba
104
src/list/sort.c
Normal file
104
src/list/sort.c
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user