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

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

mercurial