|
|
1.1 root 1:
2: #include <stdio.h>
3: #include <string.h>
4: #include <stdlib.h>
5: #include <assert.h>
6: #include "dict.h"
7:
8: /*#define DEBUG*/
9:
10: #ifndef MIN
11: # define MIN(a,b) ((a)<(b) ? (a) : (b))
12: #endif
13: #ifndef MAX
14: # define MAX(a,b) ((a)>(b) ? (a) : (b))
15: #endif
16:
17: #define _NONE -1
18: #define LEFT 0
19: #define RIGHT 1
20: #define _ERR 2
21:
22: static int parent_side (const struct Node *node)
23: {
24: if (node->parent == NULL)
25: return _NONE;
26: else if (node->parent->child[LEFT] == node)
27: return LEFT;
28: else if (node->parent->child[RIGHT] == node)
29: return RIGHT;
30: else
31: return _ERR;
32: }
33:
34: static void print_tree (const struct Node *node, int depth)
35: {
36: int i;
37: //assert (depth < 10);
38: if (depth==0) printf ("Tree printout:\n");
39: if (!node) return;
40: for (i=0; i<depth; i++) {
41: printf ("\t");
42: }
43:
44: switch (parent_side (node)) {
45: case _NONE: printf ("+ "); break;
46: case LEFT: printf ("L "); break;
47: case RIGHT: printf ("R "); break;
48: default: printf ("? "); break;
49: }
50: printf ("\"%s\" bal %d: obj %x\n", node->key, node->balance, (int)node->obj);
51:
52: if (node->child[LEFT]) print_tree (node->child[LEFT], depth+1);
53: if (node->child[RIGHT]) print_tree (node->child[RIGHT], depth+1);
54: }
55:
56: static struct Node *alloc_node ()
57: {
58: struct Node *node = (struct Node *) malloc (sizeof (struct Node));
59: memset (node, 0, sizeof (struct Node));
60: return node;
61: }
62:
63: static void free_node (struct Node *node)
64: {
65: if (node->key) free (node->key);
66: free (node);
67: }
68:
69: static void set_node (struct Node *node, const char *key, void *obj)
70: {
71: node->key = (char *) malloc (strlen(key)+1);
72: strcpy (node->key, key);
73: node->obj = obj;
74: }
75:
76: /*
77: * This node is unbalanced :-o
78: * Returns new top node.
79: */
80: static struct Node *balance_node (struct Dict *tree, struct Node *high)
81: {
82: struct Node *mid = NULL;
83: struct Node *low = NULL;
84:
85: /* Single, rightwards */
86: if ((high->balance == +2) && (high->child[RIGHT]->balance >= 0)) {
87: mid = high->child[RIGHT];
88: low = mid->child[RIGHT];
89:
90: /* this one ends at top */
91: mid->parent = high->parent;
92: switch (parent_side (high)) {
93: case _NONE: tree->root = mid; break;
94: case LEFT: mid->parent->child[LEFT] = mid; break;
95: case RIGHT: mid->parent->child[RIGHT] = mid; break;
96: }
97:
98: high->child[RIGHT] = mid->child[LEFT];
99: if (mid->child[LEFT]) mid->child[LEFT]->parent = high;
100:
101: mid->child[LEFT] = high;
102: high->parent = mid;
103:
104: high->balance = high->balance - 1 - MAX (mid->balance, 0);
105: mid->balance = mid->balance - 1 + MIN (high->balance, 0);
106:
107: return mid;
108: }
109: /* Single, leftwards */
110: else if ((high->balance == -2) && (high->child[LEFT]->balance <= 0)) {
111: mid = high->child[LEFT];
112: low = mid->child[LEFT];
113:
114: /* this one ends at top */
115: mid->parent = high->parent;
116: switch (parent_side (high)) {
117: case _NONE: tree->root = mid; break;
118: case LEFT: mid->parent->child[LEFT] = mid; break;
119: case RIGHT: mid->parent->child[RIGHT] = mid; break;
120: }
121:
122: high->child[LEFT] = mid->child[RIGHT];
123: if (mid->child[RIGHT]) mid->child[RIGHT]->parent = high;
124:
125: mid->child[RIGHT] = high;
126: high->parent = mid;
127:
128: high->balance = high->balance + 1 - MIN (mid->balance, 0);
129: mid->balance = mid->balance + 1 + MAX (high->balance, 0);
130:
131: return mid;
132: }
133: /* Double, rightwards */
134: else if ((high->balance == +2) && (high->child[RIGHT]->balance == -1)) {
135: mid = high->child[RIGHT];
136: low = mid->child[LEFT];
137: /* this one ends at top */
138: low->parent = high->parent;
139: switch (parent_side (high)) {
140: case _NONE: tree->root = low; break;
141: case LEFT: low->parent->child[LEFT] = low; break;
142: case RIGHT: low->parent->child[RIGHT] = low; break;
143: }
144:
145: high->child[RIGHT] = low->child[LEFT];
146: if (low->child[LEFT]) low->child[LEFT]->parent = high;
147:
148: mid->child[LEFT] = low->child[RIGHT];
149: if (low->child[RIGHT]) low->child[RIGHT]->parent = mid;
150:
151: low->child[LEFT] = high;
152: high->parent = low;
153:
154: low->child[RIGHT] = mid;
155: mid->parent = low;
156:
157: high->balance = -MAX (low->balance, 0);
158: mid->balance = -MIN (low->balance, 0);
159: low->balance = 0;
160:
161: return low;
162: }
163: /* Double, leftwards */
164: else if ((high->balance == -2) && (high->child[LEFT]->balance == +1)) {
165: mid = high->child[LEFT];
166: low = mid->child[RIGHT];
167:
168: /* this one ends at top */
169: low->parent = high->parent;
170: switch (parent_side (high)) {
171: case _NONE: tree->root = low; break;
172: case LEFT: low->parent->child[LEFT] = low; break;
173: case RIGHT: low->parent->child[RIGHT] = low; break;
174: }
175:
176: high->child[LEFT] = low->child[RIGHT];
177: if (low->child[RIGHT]) low->child[RIGHT]->parent = high;
178:
179: mid->child[RIGHT] = low->child[LEFT];
180: if (low->child[LEFT]) low->child[LEFT]->parent = mid;
181:
182: low->child[RIGHT] = high;
183: high->parent = low;
184:
185: low->child[LEFT] = mid;
186: mid->parent = low;
187:
188: high->balance = -MIN (low->balance, 0);
189: mid->balance = -MAX (low->balance, 0);
190: low->balance = 0;
191:
192: return low;
193: } else {
194: assert ("This shouldn't happen in balance_node()");
195: return NULL;
196: }
197: }
198:
199: void dict_init (struct Dict *tree)
200: {
201: tree->root = NULL;
202: tree->len = 0;
203: }
204:
205: static void node_recurse_free (struct Node *node)
206: {
207: if (node->child[LEFT]) {
208: node_recurse_free (node->child[LEFT]);
209: }
210: if (node->child[RIGHT]) {
211: node_recurse_free (node->child[RIGHT]);
212: }
213: free_node (node);
214: }
215:
216: void dict_free (struct Dict *tree)
217: {
218: node_recurse_free (tree->root);
219: }
220:
221: void dict_remove (struct Dict *tree, const char *key)
222: {
223: int side;
224: struct Node *to_remove;
225: struct Node *iter;
226: struct Node *rem_pos;
227: int rem_dir;
228:
229: to_remove = dict_get (tree, key);
230:
231: if (to_remove == NULL) return;
232:
233: side = parent_side (to_remove);
234:
235: /* easy. no children */
236: if ((to_remove->child[LEFT] == NULL) && (to_remove->child[RIGHT] == NULL)) {
237: if (side == _NONE) {
238: tree->root = NULL;
239: } else {
240: to_remove->parent->child[side] = NULL;
241: }
242: rem_pos = to_remove->parent;
243: rem_dir = side;
244: } else if (to_remove->child[LEFT] == NULL) {
245: /* only righthand child. give it to parent */
246: if (side == _NONE) {
247: tree->root = to_remove->child[RIGHT];
248: } else {
249: to_remove->parent->child[side] = to_remove->child[RIGHT];
250: }
251: to_remove->child[RIGHT]->parent = to_remove->parent;
252:
253: rem_pos = to_remove->parent;
254: rem_dir = side;
255: } else if (to_remove->child[RIGHT] == NULL) {
256: /* only lefthand child. give it to parent... */
257: if (side == _NONE) {
258: tree->root = to_remove->child[LEFT];
259: } else {
260: to_remove->parent->child[side] = to_remove->child[LEFT];
261: }
262: to_remove->child[LEFT]->parent = to_remove->parent;
263:
264: rem_pos = to_remove->parent;
265: rem_dir = side;
266: } else {
267: /* 2 children.. more complex. we give the parent the
268: * rightmost child of the left child :-) */
269: iter = to_remove->child[LEFT];
270: while (iter->child[RIGHT]) {
271: iter = iter->child[RIGHT];
272: }
273:
274: /* maybe it has a left child. reparent it if so */
275: if (iter->child[LEFT]) {
276: iter->child[LEFT]->parent = iter->parent;
277: iter->parent->child[parent_side (iter)] = iter->child[LEFT];
278: iter->child[LEFT] = NULL;
279: } else {
280: iter->parent->child[parent_side (iter)] = NULL;
281: }
282: rem_pos = iter->parent;
283: rem_dir = RIGHT;
284: if (rem_pos == to_remove) {
285: rem_pos = iter;
286: rem_dir = LEFT;
287: }
288:
289: switch (parent_side (to_remove)) {
290: case _NONE:
291: tree->root = iter;
292: iter->parent = NULL;
293: break;
294: case LEFT:
295: iter->parent = to_remove->parent;
296: iter->parent->child[LEFT] = iter;
297: break;
298: case RIGHT:
299: iter->parent = to_remove->parent;
300: iter->parent->child[RIGHT] = iter;
301: break;
302: }
303:
304: if ((to_remove->child[LEFT] != NULL) &&
305: (to_remove->child[LEFT] != iter)) {
306: iter->child[LEFT] = to_remove->child[LEFT];
307: iter->child[LEFT]->parent = iter;
308: } else {
309: iter->child[LEFT] = NULL;
310: }
311: if ((to_remove->child[RIGHT] != NULL) &&
312: (to_remove->child[RIGHT] != iter)) {
313: iter->child[RIGHT] = to_remove->child[RIGHT];
314: iter->child[RIGHT]->parent = iter;
315: } else {
316: iter->child[RIGHT] = NULL;
317: }
318: iter->balance = to_remove->balance;
319: }
320: /* Iter should now be parent of [re]moved node.
321: * we need to recalculate balance */
322: iter = rem_pos;
323: assert (iter != to_remove);
324: /* AVL rotate if required */
325: /* Go back through parents seeing if some cunt is fucked */
326: while (iter) {
327: switch (rem_dir) {
328: case LEFT: side = -1; break;
329: case RIGHT: side = 1; break;
330: }
331: iter->balance -= side;
332:
333: /* unbalanced node */
334: if (abs (iter->balance) >= 2) {
335: iter = balance_node (tree, iter);
336: if (iter->balance != 0) return;
337: } else if (abs (iter->balance) == 1) {
338: break;
339: }
340: rem_dir = parent_side (iter);
341: iter = iter->parent;
342: }
343: free_node (to_remove);
344: }
345:
346: struct Node *dict_get (struct Dict *tree, const char *key)
347: {
348: int cmp;
349: struct Node *parent = NULL;
350: struct Node *node;
351:
352: if (tree->root == NULL) {
353: return NULL;
354: }
355:
356: node = tree->root;
357: while (1) {
358: /* Not found */
359: if ((parent) && (node == NULL))
360: return NULL;
361:
362: cmp = strcmp (node->key, key);
363:
364: if (cmp < 0) {
365: parent = node;
366: node = node->child[LEFT];
367: } else if (cmp > 0) {
368: parent = node;
369: node = node->child[RIGHT];
370: } else {
371: /* match */
372: return node;
373: }
374: }
375:
376:
377: }
378:
379: /*
380: * Returns 1 if key is new, otherwise zero.
381: */
382: int dict_set (struct Dict *tree, const char *key, void *obj)
383: {
384: int cmp = 0;
385: int side;
386: struct Node *parent = NULL;
387: struct Node *node;
388:
389: if (tree->root == NULL) {
390: tree->root = alloc_node ();
391: set_node (tree->root, key, obj);
392: tree->len++;
393: return 1;
394: }
395:
396: node = tree->root;
397: while (1) {
398: /* Found adding position */
399: if ((parent) && (node == NULL))
400: break;
401: cmp = strcmp (node->key, key);
402:
403: if (cmp < 0) {
404: parent = node;
405: node = node->child[LEFT];
406: } else if (cmp > 0) {
407: parent = node;
408: node = node->child[RIGHT];
409: } else {
410: /* match */
411: node->obj = obj;
412: return 0;
413: }
414: }
415:
416: /* add new */
417: node = alloc_node ();
418: set_node (node, key, obj);
419: tree->len++;
420: if (cmp < 0) {
421: parent->child[LEFT] = node;
422: } else {
423: parent->child[RIGHT] = node;
424: }
425: node->parent = parent;
426:
427: /* AVL rotate if required */
428: /* Go back through parents seeing if some cunt is fucked */
429: while (parent) {
430: if (parent->child[LEFT] == node) {
431: side = -1;
432: } else {
433: side = +1;
434: }
435:
436: parent->balance += side;
437:
438: /* unbalanced node */
439: if (abs (parent->balance) >= 2) {
440: parent = balance_node (tree, parent);
441: if (parent->balance == 0) return 1;
442: } else if (parent->balance == 0) {
443: break;
444: }
445: node = parent;
446: parent = node->parent;
447: }
448: /* nothing unbalanced */
449: return 1;
450: }
451:
452: #ifdef DEBUG
453: /*
454: * Asserts if the tree's balance is fucked in some way.
455: */
456: static int node_isbalanced (struct Node *node)
457: {
458: /* heights of trees */
459: int left = 0;
460: int right = 0;
461:
462: if (node->child[LEFT]) {
463: left += 1 + abs (node_isbalanced (node->child[LEFT]));
464: }
465: if (node->child[RIGHT]) {
466: right += 1 + abs (node_isbalanced (node->child[RIGHT]));
467: }
468:
469: //printf ("Node '%s' has height %d, balance %d (claims %d)\n", node->key, MAX (left, right), right-left, node->balance);
470:
471: assert ((right-left) == node->balance);
472: assert (abs (right-left) < 2);
473:
474: return MAX (left, right);
475: }
476:
477: #define TEST_SIZE 40
478:
479: int main (void)
480: {
481: int i;
482: int errs;
483: char buf[20];
484: char *keys[TEST_SIZE];
485: void *objs[TEST_SIZE];
486: struct Dict t;
487: struct Node *n;
488:
489: srand (4);
490: dict_init (&t);
491:
492: for (i=0; i<TEST_SIZE; i++) {
493: /* Make key */
494: sprintf(buf, "Node%d:%02d", rand(), i);
495: keys[i] = (char *) malloc (strlen(buf)+1);
496: strcpy (keys[i], buf);
497: /* Data */
498: objs[i] = (void *) rand();
499:
500: dict_set (&t, keys[i], objs[i]);
501: }
502:
503: print_tree (t.root, 0);
504: node_isbalanced (t.root);
505:
506: for (i=0, errs=0; i<TEST_SIZE; i++) {
507: /* Check if returned keys are correct */
508: n = dict_get (&t, keys[i]);
509: if ((n == NULL) || (n->obj != objs[i])) {
510: errs++;
511: }
512: }
513: printf ("%d incorrect gets.\n", errs);
514:
515: printf ("Removing half the keys...\n");
516: /* now remove half of them */
517: for (i=0; i<6*TEST_SIZE/8; i++) {
518: dict_remove (&t, keys[i]);
519: }
520: print_tree (t.root, 0);
521:
522: for (i=6*TEST_SIZE/8, errs=0; i<TEST_SIZE; i++) {
523: /* Check if returned keys are correct */
524: n = dict_get (&t, keys[i]);
525: if ((n == NULL) || (n->obj != objs[i])) {
526: errs++;
527: }
528: }
529: printf ("%d incorrect gets.\n", errs);
530: node_isbalanced (t.root);
531:
532: dict_free (&t);
533:
534: return 0;
535: }
536: #endif /* DEBUG */
537:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.