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