ucx/dlist.c

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 67
27e67e725d35
permissions
-rw-r--r--

replaced qsort with natural merge sort

     1 #include "dlist.h"
     3 UcxDlist *ucx_dlist_clone(UcxDlist *l, copy_func fnc, void *data) {
     4     UcxDlist *ret = NULL;
     5     while (l != NULL) {
     6         if (fnc != NULL) {
     7             ret = ucx_dlist_append(ret, fnc(l->data, data));
     8         } else {
     9             ret = ucx_dlist_append(ret, l->data);
    10         }
    11         l = l->next;
    12     }
    13     return ret;
    14 }
    16 int ucx_dlist_equals(UcxDlist *l1, UcxDlist *l2, cmp_func fnc, void* data) {
    17     if (l1 == l2) return 1;
    19     while (l1 != NULL && l2 != NULL) {
    20         if (fnc == NULL) {
    21             if (l1->data != l2->data) return 0;
    22         } else {
    23             if (fnc(l1->data, l2->data, data) != 0) return 0;
    24         }
    25         l1 = l1->next;
    26         l2 = l2->next;
    27     }
    29     return (l1 == NULL && l2 == NULL);
    30 }
    32 void ucx_dlist_free(UcxDlist *l) {
    33     UcxDlist *e = l, *f;
    34     while (e != NULL) {
    35         f = e;
    36         e = e->next;
    37         free(f);
    38     }
    39 }
    41 UcxDlist *ucx_dlist_append(UcxDlist *l, void *data)  {
    42     UcxDlist *nl = (UcxDlist*) malloc(sizeof(UcxDlist));
    43     if (nl == NULL) return NULL;
    45     nl->data = data;
    46     nl->next = NULL;
    47     if (l == NULL) {
    48         nl->prev = NULL;
    49         return nl;
    50     } else {
    51         UcxDlist *t = ucx_dlist_last(l);
    52         t->next = nl;
    53         nl->prev = t;
    54         return l;
    55     }
    56 }
    58 UcxDlist *ucx_dlist_prepend(UcxDlist *l, void *data) {
    59     UcxDlist *nl = ucx_dlist_append(NULL, data);
    60     if (nl == NULL) return NULL;
    62     if (l != NULL) {
    63         nl->next = l;
    64         l->prev = nl;
    65     }
    66     return nl;
    67 }
    69 UcxDlist *ucx_dlist_concat(UcxDlist *l1, UcxDlist *l2) {
    70     if (l1 == NULL) {
    71         return l2;
    72     } else {
    73         UcxDlist *last = ucx_dlist_last(l1);
    74         last->next = l2;
    75         l2->prev = last;
    76         return l1;
    77     }
    78 }
    80 UcxDlist *ucx_dlist_last(UcxDlist *l) {
    81     if (l == NULL) return NULL;
    83     UcxDlist *e = l;
    84     while (e->next != NULL) {
    85         e = e->next;
    86     }
    87     return e;
    88 }
    90 UcxDlist *ucx_dlist_get(UcxDlist *l, int index) {
    91     if (l == NULL) return NULL;
    93     UcxDlist *e = l;
    94     while (e->next != NULL && index > 0) {
    95         e = e->next;
    96         index--;
    97     }
    99     return index == 0 ? e : NULL;
   100 }
   102 size_t ucx_dlist_size(UcxDlist *l) {
   103     if (l == NULL) return 0;
   105     UcxDlist *e = l;
   106     size_t s = 1;
   107     while (e->next != NULL) {
   108         e = e->next;
   109         s++;
   110     }
   112     return s;
   113 }
   115 UcxDlist *ucx_dlist_sort_merge(int length,
   116         UcxDlist* ls, UcxDlist* rs, UcxDlist* le, UcxDlist* re,
   117         cmp_func fnc, void* data) {
   118     UcxDlist *sorted[length];
   119     UcxDlist *rc, *lc;
   121     lc = ls; rc = rs;
   122     int n = 0;
   123     while (lc != le && rc != re) {
   124         if (fnc(lc->data, rc->data, data) <= 0) {
   125             sorted[n] = lc;
   126             lc = lc->next;
   127         } else {
   128             sorted[n] = rc;
   129             rc = rc->next;
   130         }
   131         n++;
   132     }
   133     while (lc != le) {
   134         sorted[n] = lc;
   135         lc = lc->next;
   136         n++;
   137     }
   138     while (rc != re) {
   139         sorted[n] = rc;
   140         rc = rc->next;
   141         n++;
   142     }
   144     // Update pointer
   145     sorted[0]->prev = NULL;
   146     for (int i = 0 ; i < length-1 ; i++) {
   147         sorted[i]->next = sorted[i+1];
   148         sorted[i+1]->prev = sorted[i];
   149     }
   150     sorted[length-1]->next = NULL;
   152     return sorted[0];
   153 }
   155 UcxDlist *ucx_dlist_sort(UcxDlist *l, cmp_func fnc, void *data) {
   156     if (l == NULL) {
   157         return NULL;
   158     }
   160     UcxDlist *lc;
   161     int ln = 1;
   163     UcxDlist *ls = l, *le;
   164     lc = ls;
   165     while (lc->next != NULL && fnc(lc->next->data, lc->data, data) > 0) {
   166         lc = lc->next;
   167         ln++;
   168     }
   169     le = lc->next;
   171     UcxDlist *rs = le, *re;
   172     if (rs == NULL) {
   173         return l; // this list is already sorted :)
   174     } else {
   175         UcxDlist *rc;
   176         int rn = 1;
   177         rc = rs;
   178         while (rc->next != NULL && fnc(rc->next->data, rc->data, data) > 0) {
   179             rc = rc->next;
   180             rn++;
   181         }
   182         re = rc->next;
   184         // Something left? Sort it!
   185         UcxDlist *remainder = re;
   186         size_t remainder_length = ucx_dlist_size(remainder);
   187         if (remainder != NULL) {
   188             remainder = ucx_dlist_sort(remainder, fnc, data);
   189         }
   191         // {ls,...,le->prev} and {rs,...,re->prev} are sorted - merge them
   192         UcxDlist *sorted = ucx_dlist_sort_merge(ln+rn,
   193                 ls, rs, le, re,
   194                 fnc, data);
   196         // merge sorted list with (also sorted) remainder
   197         l = ucx_dlist_sort_merge(ln+rn+remainder_length,
   198                 sorted, remainder, NULL, NULL,
   199                 fnc, data);
   201         return l;
   202     }
   203 }
   205 /* dlist specific functions */
   206 UcxDlist *ucx_dlist_first(UcxDlist *l) {
   207     if (l == NULL) return NULL;
   209     UcxDlist *e = l;
   210     while (e->prev != NULL) {
   211         e = e->prev;
   212     }
   213     return e;
   214 }
   216 UcxDlist *ucx_dlist_remove(UcxDlist *l, UcxDlist *e) {
   217     if (e->prev == NULL) {
   218         if(e->next != NULL) {
   219             e->next->prev = NULL;
   220             l = e->next;
   221         } else {
   222             l = NULL;
   223         }
   225     } else {
   226         e->prev->next = e->next;
   227         e->next->prev = e->prev;
   228     }
   229     free(e);
   230     return l;
   231 }

mercurial