ucx/list.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 "list.h"
     3 UcxList *ucx_list_clone(UcxList *l, copy_func fnc, void *data) {
     4     UcxList *ret = NULL;
     5     while (l != NULL) {
     6         if (fnc != NULL) {
     7             ret = ucx_list_append(ret, fnc(l->data, data));
     8         } else {
     9             ret = ucx_list_append(ret, l->data);
    10         }
    11         l = l->next;
    12     }
    13     return ret;
    14 }
    16 int ucx_list_equals(UcxList *l1, UcxList *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_list_free(UcxList *l) {
    33     UcxList *e = l, *f;
    34     while (e != NULL) {
    35         f = e;
    36         e = e->next;
    37         free(f);
    38     }
    39 }
    41 UcxList *ucx_list_append(UcxList *l, void *data)  {
    42     UcxList *nl = (UcxList*) malloc(sizeof(UcxList));
    43     if (nl == NULL) return NULL;
    45     nl->data = data;
    46     nl->next = NULL;
    47     if (l == NULL) {
    48         return nl;
    49     } else {
    50         UcxList *t = ucx_list_last(l);
    51         t->next = nl;
    52         return l;
    53     }
    54 }
    56 UcxList *ucx_list_prepend(UcxList *l, void *data) {
    57     UcxList *nl = ucx_list_append(NULL, data);
    58     if (nl == NULL) return NULL;
    60     if (l != NULL) {
    61         nl->next = l;
    62     }
    63     return nl;
    64 }
    66 UcxList *ucx_list_concat(UcxList *l1, UcxList *l2) {
    67     if (l1 == NULL) {
    68         return l2;
    69     } else {
    70         UcxList *last = ucx_list_last(l1);
    71         last->next = l2;
    72         return l1;
    73     }
    74 }
    76 UcxList *ucx_list_last(UcxList *l) {
    77     if (l == NULL) return NULL;
    79     UcxList *e = l;
    80     while (e->next != NULL) {
    81         e = e->next;
    82     }
    83     return e;
    84 }
    86 UcxList *ucx_list_get(UcxList *l, int index) {
    87     if (l == NULL) return NULL;
    89     UcxList *e = l;
    90     while (e->next != NULL && index > 0) {
    91         e = e->next;
    92         index--;
    93     }
    95     return index == 0 ? e : NULL;
    96 }
    98 size_t ucx_list_size(UcxList *l) {
    99     if (l == NULL) return 0;
   101     UcxList *e = l;
   102     size_t s = 1;
   103     while (e->next != NULL) {
   104         e = e->next;
   105         s++;
   106     }
   108     return s;
   109 }
   111 UcxList *ucx_list_sort_merge(int length,
   112         UcxList* ls, UcxList* rs, UcxList* le, UcxList* re,
   113         cmp_func fnc, void* data) {
   114     UcxList *sorted[length];
   115     UcxList *rc, *lc;
   117     lc = ls; rc = rs;
   118     int n = 0;
   119     while (lc != le && rc != re) {
   120         if (fnc(lc->data, rc->data, data) <= 0) {
   121             sorted[n] = lc;
   122             lc = lc->next;
   123         } else {
   124             sorted[n] = rc;
   125             rc = rc->next;
   126         }
   127         n++;
   128     }
   129     while (lc != le) {
   130         sorted[n] = lc;
   131         lc = lc->next;
   132         n++;
   133     }
   134     while (rc != re) {
   135         sorted[n] = rc;
   136         rc = rc->next;
   137         n++;
   138     }
   140     // Update pointer
   141     for (int i = 0 ; i < length-1 ; i++) {
   142         sorted[i]->next = sorted[i+1];
   143     }
   144     sorted[length-1]->next = NULL;
   146     return sorted[0];
   147 }
   149 UcxList *ucx_list_sort(UcxList *l, cmp_func fnc, void *data) {
   150     if (l == NULL) {
   151         return NULL;
   152     }
   154     UcxList *lc;
   155     int ln = 1;
   157     UcxList *ls = l, *le;
   158     lc = ls;
   159     while (lc->next != NULL && fnc(lc->next->data, lc->data, data) > 0) {
   160         lc = lc->next;
   161         ln++;
   162     }
   163     le = lc->next;
   165     UcxList *rs = le, *re;
   166     if (rs == NULL) {
   167         return l; // this list is already sorted :)
   168     } else {
   169         UcxList *rc;
   170         int rn = 1;
   171         rc = rs;
   172         while (rc->next != NULL && fnc(rc->next->data, rc->data, data) > 0) {
   173             rc = rc->next;
   174             rn++;
   175         }
   176         re = rc->next;
   178         // Something left? Sort it!
   179         UcxList *remainder = re;
   180         size_t remainder_length = ucx_list_size(remainder);
   181         if (remainder != NULL) {
   182             remainder = ucx_list_sort(remainder, fnc, data);
   183         }
   185         // {ls,...,le->prev} and {rs,...,re->prev} are sorted - merge them
   186         UcxList *sorted = ucx_list_sort_merge(ln+rn,
   187                 ls, rs, le, re,
   188                 fnc, data);
   190         // merge sorted list with (also sorted) remainder
   191         l = ucx_list_sort_merge(ln+rn+remainder_length,
   192                 sorted, remainder, NULL, NULL,
   193                 fnc, data);
   195         return l;
   196     }
   197 }
   199 /* list specific functions */
   200 UcxList *ucx_list_remove(UcxList *l, UcxList *e) {
   201     if (e == l) {
   202         l = e->next;
   203         free(e);
   204     } else {
   205         UcxList *f = l;
   206         while (f->next != NULL && f->next != e) {
   207             f = f->next;
   208         }
   209         /* perform remove if this element is found in this list */
   210         if (f->next == e) {
   211             f->next = e->next;
   212             free(e);
   213         }
   214     }
   215     return l;
   216 }

mercurial