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