replaced qsort with natural merge sort

Thu, 16 Aug 2012 12:36:23 +0200

author
Mike Becker <universe@uap-core.de>
date
Thu, 16 Aug 2012 12:36:23 +0200
changeset 37
ec296899d12f
parent 36
a9d656e4f7ce
child 38
35f67a8ef875

replaced qsort with natural merge sort

ucx/dlist.c file | annotate | diff | comparison | revisions
ucx/list.c file | annotate | diff | comparison | revisions
     1.1 --- a/ucx/dlist.c	Thu Aug 16 11:31:16 2012 +0200
     1.2 +++ b/ucx/dlist.c	Thu Aug 16 12:36:23 2012 +0200
     1.3 @@ -112,64 +112,94 @@
     1.4      return s;
     1.5  }
     1.6  
     1.7 -int ucx_dlist_qsort_devide(UcxDlist** list, int l, int r, cmp_func f, void* d) {
     1.8 -    int i = l;
     1.9 -    int j = r - 1;
    1.10 -    void *p = list[r]->data;
    1.11 -    UcxDlist *b;
    1.12 +UcxDlist *ucx_dlist_sort_merge(int length,
    1.13 +        UcxDlist* ls, UcxDlist* rs, UcxDlist* le, UcxDlist* re,
    1.14 +        cmp_func fnc, void* data) {
    1.15 +    UcxDlist *sorted[length];
    1.16 +    UcxDlist *rc, *lc;
    1.17  
    1.18 -    do {
    1.19 -        while (i < r && f(list[i]->data, p, d) <= 0) i++;
    1.20 -        while (j > l && f(list[j]->data, p, d) >= 0) j--;
    1.21 -        if (i < j) {
    1.22 -            b = list[i];
    1.23 -            list[i] = list[j];
    1.24 -            list[j] = b;
    1.25 +    lc = ls; rc = rs;
    1.26 +    int n = 0;
    1.27 +    while (lc != le && rc != re) {
    1.28 +        if (fnc(lc->data, rc->data, data) <= 0) {
    1.29 +            sorted[n] = lc;
    1.30 +            lc = lc->next;
    1.31 +        } else {
    1.32 +            sorted[n] = rc;
    1.33 +            rc = rc->next;
    1.34          }
    1.35 -    } while (i < j);
    1.36 -
    1.37 -    if (f(list[i]->data, p, d) > 0) {
    1.38 -        b = list[r];
    1.39 -        list[r] = list[i];
    1.40 -        list[i] = b;
    1.41 +        n++;
    1.42 +    }
    1.43 +    while (lc != le) {
    1.44 +        sorted[n] = lc;
    1.45 +        lc = lc->next;
    1.46 +        n++;
    1.47 +    }
    1.48 +    while (rc != re) {
    1.49 +        sorted[n] = rc;
    1.50 +        rc = rc->next;
    1.51 +        n++;
    1.52      }
    1.53  
    1.54 -    return i;
    1.55 -}
    1.56 +    // Update pointer
    1.57 +    sorted[0]->prev = NULL;
    1.58 +    for (int i = 0 ; i < length-1 ; i++) {
    1.59 +        sorted[i]->next = sorted[i+1];
    1.60 +        sorted[i+1]->prev = sorted[i];
    1.61 +    }
    1.62 +    sorted[length-1]->next = NULL;
    1.63  
    1.64 -void ucx_dlist_qsort_sort(UcxDlist** list, int l, int r, cmp_func f, void* d) {
    1.65 -    if (l < r) {
    1.66 -        int m = ucx_dlist_qsort_devide(list, l, r, f, d);
    1.67 -        ucx_dlist_qsort_sort(list, l, m-1, f, d);
    1.68 -        ucx_dlist_qsort_sort(list, m+1, r, f, d);
    1.69 -    }
    1.70 +    return sorted[0];
    1.71  }
    1.72  
    1.73  UcxDlist *ucx_dlist_sort(UcxDlist *l, cmp_func fnc, void *data) {
    1.74      if (l == NULL) {
    1.75          return NULL;
    1.76      }
    1.77 -    size_t n = ucx_dlist_size(l);
    1.78 -    if (n == 1) {
    1.79 +
    1.80 +    UcxDlist *lc;
    1.81 +    int ln = 1;
    1.82 +
    1.83 +    UcxDlist *ls = l, *le;
    1.84 +    lc = ls;
    1.85 +    while (lc->next != NULL && fnc(lc->next->data, lc->data, data) > 0) {
    1.86 +        lc = lc->next;
    1.87 +        ln++;
    1.88 +    }
    1.89 +    le = lc->next;
    1.90 +
    1.91 +    UcxDlist *rs = le, *re;
    1.92 +    if (rs == NULL) {
    1.93 +        return l; // this list is already sorted :)
    1.94 +    } else {
    1.95 +        UcxDlist *rc;
    1.96 +        int rn = 1;
    1.97 +        rc = rs;
    1.98 +        while (rc->next != NULL && fnc(rc->next->data, rc->data, data) > 0) {
    1.99 +            rc = rc->next;
   1.100 +            rn++;
   1.101 +        }
   1.102 +        re = rc->next;
   1.103 +
   1.104 +        // Something left? Sort it!
   1.105 +        UcxDlist *remainder = re;
   1.106 +        size_t remainder_length = ucx_dlist_size(remainder);
   1.107 +        if (remainder != NULL) {
   1.108 +            remainder = ucx_dlist_sort(remainder, fnc, data);
   1.109 +        }
   1.110 +
   1.111 +        // {ls,...,le->prev} and {rs,...,re->prev} are sorted - merge them
   1.112 +        UcxDlist *sorted = ucx_dlist_sort_merge(ln+rn,
   1.113 +                ls, rs, le, re,
   1.114 +                fnc, data);
   1.115 +
   1.116 +        // merge sorted list with (also sorted) remainder
   1.117 +        l = ucx_dlist_sort_merge(ln+rn+remainder_length,
   1.118 +                sorted, remainder, NULL, NULL,
   1.119 +                fnc, data);
   1.120 +
   1.121          return l;
   1.122      }
   1.123 -
   1.124 -    UcxDlist *entries[n];
   1.125 -    entries[0] = l;
   1.126 -    for (int i = 1 ; i < n ; i++) {
   1.127 -      entries[i] = entries[i-1]->next;
   1.128 -    }
   1.129 -
   1.130 -    ucx_dlist_qsort_sort(entries, 0, n-1, fnc, data);
   1.131 -
   1.132 -    entries[0]->prev = NULL;
   1.133 -    for (int i = 0 ; i < n-1 ; i++) {
   1.134 -      entries[i]->next = entries[i+1];
   1.135 -      entries[i+1]->prev = entries[i];
   1.136 -    }
   1.137 -    entries[n-1]->next = NULL;
   1.138 -
   1.139 -    return entries[0];
   1.140  }
   1.141  
   1.142  /* dlist specific functions */
     2.1 --- a/ucx/list.c	Thu Aug 16 11:31:16 2012 +0200
     2.2 +++ b/ucx/list.c	Thu Aug 16 12:36:23 2012 +0200
     2.3 @@ -108,62 +108,92 @@
     2.4      return s;
     2.5  }
     2.6  
     2.7 -int ucx_list_qsort_devide(UcxList** list, int l, int r, cmp_func f, void* d) {
     2.8 -    int i = l;
     2.9 -    int j = r - 1;
    2.10 -    void *p = list[r]->data;
    2.11 -    UcxList *b;
    2.12 +UcxList *ucx_list_sort_merge(int length,
    2.13 +        UcxList* ls, UcxList* rs, UcxList* le, UcxList* re,
    2.14 +        cmp_func fnc, void* data) {
    2.15 +    UcxList *sorted[length];
    2.16 +    UcxList *rc, *lc;
    2.17  
    2.18 -    do {
    2.19 -        while (i < r && f(list[i]->data, p, d) <= 0) i++;
    2.20 -        while (j > l && f(list[j]->data, p, d) >= 0) j--;
    2.21 -        if (i < j) {
    2.22 -            b = list[i];
    2.23 -            list[i] = list[j];
    2.24 -            list[j] = b;
    2.25 +    lc = ls; rc = rs;
    2.26 +    int n = 0;
    2.27 +    while (lc != le && rc != re) {
    2.28 +        if (fnc(lc->data, rc->data, data) <= 0) {
    2.29 +            sorted[n] = lc;
    2.30 +            lc = lc->next;
    2.31 +        } else {
    2.32 +            sorted[n] = rc;
    2.33 +            rc = rc->next;
    2.34          }
    2.35 -    } while (i < j);
    2.36 -
    2.37 -    if (f(list[i]->data, p, d) > 0) {
    2.38 -        b = list[r];
    2.39 -        list[r] = list[i];
    2.40 -        list[i] = b;
    2.41 +        n++;
    2.42 +    }
    2.43 +    while (lc != le) {
    2.44 +        sorted[n] = lc;
    2.45 +        lc = lc->next;
    2.46 +        n++;
    2.47 +    }
    2.48 +    while (rc != re) {
    2.49 +        sorted[n] = rc;
    2.50 +        rc = rc->next;
    2.51 +        n++;
    2.52      }
    2.53  
    2.54 -    return i;
    2.55 -}
    2.56 +    // Update pointer
    2.57 +    for (int i = 0 ; i < length-1 ; i++) {
    2.58 +        sorted[i]->next = sorted[i+1];
    2.59 +    }
    2.60 +    sorted[length-1]->next = NULL;
    2.61  
    2.62 -void ucx_list_qsort_sort(UcxList** list, int l, int r, cmp_func f, void* d) {
    2.63 -    if (l < r) {
    2.64 -        int m = ucx_list_qsort_devide(list, l, r, f, d);
    2.65 -        ucx_list_qsort_sort(list, l, m-1, f, d);
    2.66 -        ucx_list_qsort_sort(list, m+1, r, f, d);
    2.67 -    }
    2.68 +    return sorted[0];
    2.69  }
    2.70  
    2.71  UcxList *ucx_list_sort(UcxList *l, cmp_func fnc, void *data) {
    2.72      if (l == NULL) {
    2.73          return NULL;
    2.74      }
    2.75 -    size_t n = ucx_list_size(l);
    2.76 -    if (n == 1) {
    2.77 +
    2.78 +    UcxList *lc;
    2.79 +    int ln = 1;
    2.80 +
    2.81 +    UcxList *ls = l, *le;
    2.82 +    lc = ls;
    2.83 +    while (lc->next != NULL && fnc(lc->next->data, lc->data, data) > 0) {
    2.84 +        lc = lc->next;
    2.85 +        ln++;
    2.86 +    }
    2.87 +    le = lc->next;
    2.88 +
    2.89 +    UcxList *rs = le, *re;
    2.90 +    if (rs == NULL) {
    2.91 +        return l; // this list is already sorted :)
    2.92 +    } else {
    2.93 +        UcxList *rc;
    2.94 +        int rn = 1;
    2.95 +        rc = rs;
    2.96 +        while (rc->next != NULL && fnc(rc->next->data, rc->data, data) > 0) {
    2.97 +            rc = rc->next;
    2.98 +            rn++;
    2.99 +        }
   2.100 +        re = rc->next;
   2.101 +
   2.102 +        // Something left? Sort it!
   2.103 +        UcxList *remainder = re;
   2.104 +        size_t remainder_length = ucx_list_size(remainder);
   2.105 +        if (remainder != NULL) {
   2.106 +            remainder = ucx_list_sort(remainder, fnc, data);
   2.107 +        }
   2.108 +
   2.109 +        // {ls,...,le->prev} and {rs,...,re->prev} are sorted - merge them
   2.110 +        UcxList *sorted = ucx_list_sort_merge(ln+rn,
   2.111 +                ls, rs, le, re,
   2.112 +                fnc, data);
   2.113 +
   2.114 +        // merge sorted list with (also sorted) remainder
   2.115 +        l = ucx_list_sort_merge(ln+rn+remainder_length,
   2.116 +                sorted, remainder, NULL, NULL,
   2.117 +                fnc, data);
   2.118 +
   2.119          return l;
   2.120      }
   2.121 -
   2.122 -    UcxList *entries[n];
   2.123 -    entries[0] = l;
   2.124 -    for (int i = 1 ; i < n ; i++) {
   2.125 -      entries[i] = entries[i-1]->next;
   2.126 -    }
   2.127 -
   2.128 -    ucx_list_qsort_sort(entries, 0, n-1, fnc, data);
   2.129 -
   2.130 -    for (int i = 0 ; i < n-1 ; i++) {
   2.131 -      entries[i]->next = entries[i+1];
   2.132 -    }
   2.133 -    entries[n-1]->next = NULL;
   2.134 -
   2.135 -    return entries[0];
   2.136  }
   2.137  
   2.138  /* list specific functions */

mercurial