Annotation of libwww/Library/src/HTBTree.c, revision 2.5
1.1 timbl 1: /* Binary Tree for sorting things
2: ** ==============================
3: ** Author: Arthur Secret
4: */
5:
6:
7: #include "HTUtils.h"
8: #include "HTBTree.h"
9: #include <stdlib.h>
10: #include <string.h>
11:
12: #define MAX(a,b) ((a)>(b)?(a):(b))
13:
14:
15:
16:
17:
18: PUBLIC HTBTree * HTBTree_new ARGS1(HTComparer, comp)
19: /*********************************************************
20: ** This function returns an HTBTree with memory allocated
21: ** for it when given a mean to compare things
22: */
23: {
24: HTBTree * tree = (HTBTree *)malloc(sizeof(HTBTree));
25: if (tree==NULL) outofmem(__FILE__, "HTBTree_new");
26:
27: tree->compare = comp;
28: tree->top = NULL;
29:
30: return tree;
31: }
32:
33:
34:
35:
36:
37: PUBLIC void HTBTree_free ARGS1(HTBTree*, tree)
38: /**************************************************************
39: ** This void will free the memory allocated for the whole tree
40: */
41: {
42: HTBTElement * wagazou;
43:
44: wagazou = HTBTree_next(tree,NULL);
45: while (wagazou != NULL)
46: {
47: free (wagazou);
48: wagazou = HTBTree_next(tree,wagazou);
49: }
50: free(tree);
51: }
52:
53:
54:
55:
56:
57: PUBLIC void HTBTree_add ARGS2(
58: HTBTree*, tree,
59: void*, object)
60: /**********************************************************************
61: ** This void is the core of HTBTree.c . It will
62: ** 1/ add a new element to the tree at the right place
63: ** so that the tree remains sorted
64: ** 2/ balance the tree to be as fast as possible when reading it
65: */
66: {
67: HTBTElement * leopard;
68: HTBTElement * leopard_son;
69: HTBTElement * leopard_father;
70: HTBTElement * leo_brother;
71: BOOL bouboule,bouboule2,first_correction;
72: int depth,depth2;
73: /* leopard is a pointer to the structure that is the father of the new
74: ** object "object".
75: ** leopard_son is a pointer to the structure that contains or will contain
76: ** the new object "object".
77: ** leopard_father and leo_brother are pointers that are used to modify the
78: ** depths of upper elements, when needed.
79: **
80: ** bouboule indicates by a value NO when the future father of "object" is
81: ** found.
82: ** bouboule2 indicates by a value NO when, in case of a difference of depths
83: ** < 2, the top of the tree is encountered and forbids any further try to
84: ** balance the tree.
85: ** first_correction is a boolean used to avoid infinite loops in cases
86: ** such as:
87: **
88: ** 3 3
89: ** 4 4
90: ** 5 5
91: **
92: ** 3 is used here to show that it need not be the top of the tree.
93: */
94:
95: /*
96: ** 1/ Adding of the element to the binary tree
97: */
98:
99: if (tree->top == NULL)
100: {
101: tree->top = (HTBTElement *)malloc(sizeof(HTBTElement));
102: if (tree->top == NULL) outofmem(__FILE__, "HTBTree_add");
103: tree->top->up = NULL;
104: tree->top->object = object;
105: tree->top->left = NULL;
106: tree->top->left_depth = 0;
107: tree->top->right = NULL;
108: tree->top->right_depth = 0;
109: }
110: else
111: {
112: bouboule = YES;
113: leopard = tree->top;
114: leopard_son = NULL;
115: leopard_father = NULL;
116: leo_brother = NULL;
117: while (bouboule)
118: {
119: if (tree->compare(object,leopard->object)<0)
120: {
121: if (leopard->left != NULL) leopard = leopard->left;
122: else
123: {
124: bouboule = NO;
125: leopard->left = (HTBTElement *)malloc(sizeof(HTBTElement));
126: if (leopard->left==NULL) outofmem(__FILE__, "HTBTree_add");
127: leopard_son = leopard->left;
128: leopard_son->up = leopard;
129: leopard_son->object = object;
130: leopard_son->left = NULL;
131: leopard_son->left_depth = 0;
132: leopard_son->right = NULL;
133: leopard_son->right_depth = 0;
134: }
135: }
136: if (tree->compare(object,leopard->object)>0)
137: {
138: if (leopard->right != NULL) leopard = leopard->right;
139: else
140: {
141: bouboule = NO;
142: leopard->right = (HTBTElement *)malloc(sizeof(HTBTElement));
143: if (leopard->right==NULL) outofmem(__FILE__, "HTBTree_add");
144: leopard_son = leopard->right;
145: leopard_son->up = leopard;
146: leopard_son->object = object;
147: leopard_son->left = NULL;
148: leopard_son->left_depth = 0;
149: leopard_son->right = NULL;
150: leopard_son->right_depth = 0;
151: }
152: }
153: }
154: /*
155: ** Changing of all depths that need to be changed
156: */
157: leopard_father = leopard;
158: leo_brother = leopard_son;
159: do
160: {
161: if (leopard_father->left == leo_brother)
162: {
163: depth = leopard_father->left_depth;
164: leopard_father->left_depth = 1
165: + MAX(leo_brother->right_depth,leo_brother->left_depth);
166: depth2 = leopard_father->left_depth;
167: }
168: else
169: {
170: depth = leopard_father->right_depth;
171: leopard_father->right_depth = 1
172: + MAX(leo_brother->right_depth,leo_brother->left_depth);
173: depth2 = leopard_father->right_depth;
174: }
175: leo_brother = leopard_father;
176: leopard_father = leopard_father->up;
177: } while ((depth != depth2) && (leopard_father != NULL));
178:
179:
180: /*
181: ** 2/ Balancing the binary tree, if necessary
182: */
183: bouboule2 = YES;
184: first_correction = YES;
185: while ((bouboule2) && (first_correction))
186: {
187: if ((abs(leopard->left_depth - leopard->right_depth)) < 2)
188: {
189: if (leopard->up != NULL) leopard = leopard->up;
190: else bouboule2 = NO;
191: }
192: else
193: { /* We start the process of balancing */
194:
195: first_correction = NO;
196: /*
197: ** first_correction is a boolean used to avoid infinite
198: ** loops in cases such as:
199: **
200: ** 3 3
201: ** 4 4
202: ** 5 5
203: **
204: ** 3 is used to show that it need not be the top of the tree
205: */
206:
207:
208: if (leopard->left_depth > leopard->right_depth)
209: {
210: leopard_son = leopard->left;
211: leopard->left_depth = leopard_son->right_depth;
212: leopard_son->right_depth = 1
213: + MAX(leopard->right_depth,leopard->left_depth);
214: if (leopard->up != NULL)
215: {
216: leopard_father = leopard->up;
217: leo_brother = leopard_son;
218: do
219: {
220: if (leopard_father->left == leo_brother->up)
221: {
222: depth = leopard_father->left_depth;
223: leopard_father->left_depth = 1
224: + MAX(leo_brother->left_depth,
225: leo_brother->right_depth);
226: depth2 = leopard_father->left_depth;
227: }
228: else
229: {
230: depth = leopard_father->right_depth;
231: leopard_father->right_depth = 1
232: + MAX(leo_brother->left_depth,
233: leo_brother->right_depth);
234: depth2 = leopard_father->right_depth;
235: }
236: leo_brother = leopard_father;
237: leopard_father = leopard_father->up;
238: } while ((depth != depth2) && (leopard_father != NULL));
239: leopard_father = leopard->up;
240: if (leopard_father->left == leopard)
241: {
242: /*
243: ** 3 3
244: ** 4 5
245: ** When tree 5 6 becomes 7 4
246: ** 7 8 8 6
247: **
248: ** 3 is used to show that it may not be the top of the
249: ** tree.
250: */
251: leopard_father->left = leopard_son;
252: leopard->left = leopard_son->right;
253: leopard_son->right = leopard;
254: }
255: if (leopard_father->right == leopard)
256: {
257: /*
258: ** 3 3
259: ** 4 5
260: ** When tree 5 6 becomes 7 4
261: ** 7 8 8 6
262: **
263: ** 3 is used to show that it may not be the top of the
264: ** tree
265: */
266: leopard_father->right = leopard_son;
267: leopard->left = leopard_son->right;
268: leopard_son->right = leopard;
269: }
270: leopard_son->up = leopard_father;
271: }
272: else
273: {
274: /*
275: **
276: ** 1 2
277: ** When tree 2 3 becomes 4 1
278: ** 4 5 5 3
279: **
280: ** 1 is used to show that it is the top of the tree
281: */
282: leopard_son->up = NULL;
283: leopard->left = leopard_son->right;
284: leopard_son->right = leopard;
285: }
286: leopard->up = leopard_son;
287: if (leopard->left != NULL)
288: leopard->left->up = leopard;
289: }
290: else
291: {
292: leopard_son = leopard->right;
293: leopard->right_depth = leopard_son->left_depth;
294: leopard_son->left_depth = 1 +
295: MAX(leopard->right_depth,leopard->left_depth);
296: if (leopard->up != NULL)
297: {
298: leopard_father = leopard->up;
299: leo_brother = leopard_son;
300: do
301: {
302: if (leopard_father->left == leopard)
303: {
304: depth = leopard_father->left_depth;
305: leopard_father->left_depth = 1
306: + MAX(leopard_son->left_depth,
307: leopard_son->right_depth);
308: depth2 = leopard_father->left_depth;
309: }
310: else
311: {
312: depth = leopard_father->right_depth;
313: leopard_father->right_depth = 1
314: + MAX(leopard_son->left_depth,
315: leopard_son->right_depth);
316: depth2 = leopard_father->right_depth;
317: }
318: leopard_father = leopard_father->up;
319: leo_brother = leopard_father;
320: } while ((depth != depth2) && (leopard_father != NULL));;
321: leopard_father = leopard->up;
322: if (leopard_father->left == leopard)
323: {
324: /*
325: ** 3 3
326: ** 4 6
327: ** When tree 5 6 becomes 4 8
328: ** 7 8 5 7
329: **
330: ** 3 is used to show that it may not be the top of the
331: ** tree.
332: */
333: leopard_father->left = leopard_son;
334: leopard->right = leopard_son->left;
335: leopard_son->left = leopard;
336: }
337: if (leopard_father->right == leopard)
338: {
339: /*
340: ** 3 3
341: ** 4 6
342: ** When tree 5 6 becomes 4 8
343: ** 7 8 5 7
344: **
345: ** 3 is used to show that it may not be the top of the
346: ** tree
347: */
348: leopard_father->right = leopard_son;
349: leopard->right = leopard_son->left;
350: leopard_son->left = leopard;
351: }
352: leopard_son->up = leopard_father;
353: }
354: else
355: {
356: /*
357: **
358: ** 1 3
359: ** When tree 2 3 becomes 1 5
360: ** 4 5 2 4
361: **
362: ** 1 is used to show that it is the top of the tree.
363: */
364: leopard_son->up = NULL;
365: leopard->right = leopard_son->left;
366: leopard_son->left = leopard;
367: }
368: leopard->up = leopard_son;
369: leopard->right->up = leopard;
370: }
371: }
372: }
373: while (leopard->up != NULL)
374: {
375: leopard = leopard->up;
376: }
377: tree->top = leopard;
378: }
379: }
380:
381:
382:
383: PUBLIC HTBTElement * HTBTree_next ARGS2(
384: HTBTree*, tree,
385: HTBTElement*, ele)
386: /**************************************************************************
387: ** this function returns a pointer to the leftmost element if ele is NULL,
388: ** and to the next object to the right otherways.
389: ** If no elements left, returns a pointer to NULL.
390: */
391: {
392: HTBTElement * leopard;
393: HTBTElement * leopard_father;
394:
395: if (ele == NULL)
396: {
397: leopard = tree->top;
398: if (leopard != NULL)
399: while (leopard->left != NULL)
400: leopard = leopard->left;
401: }
402: else
403: {
404: leopard = ele;
405: if (leopard->right != NULL)
406: {
407: leopard = leopard->right;
408: while (leopard->left != NULL)
409: leopard = leopard->left;
410: }
411: else
412: {
413: leopard_father = leopard->up;
414: while (leopard_father->right == leopard)
415: {
416: leopard = leopard_father;
417: leopard_father = leopard->up;
418: }
419: leopard = leopard_father;
420: }
421: }
422: return leopard;
423: }
424:
425:
426: #ifdef TEST
427: main ()
428: /******************************************************
429: ** This is just a test to show how to handle HTBTree.c
430: */
431: {
432: HTBTree * tree;
433: HTBTElement * wagazou;
434:
435: tree = HTBTree_new(strcasecmp);
436: HTBTree_add(tree,"zoo");
437: HTBTree_add(tree,"carot");
438: HTBTree_add(tree,"elephant\t");
439: HTBTree_add(tree,"coat");
440: HTBTree_add(tree,"snake");
441: HTBTree_add(tree,"Peter");
442: HTBTree_add(tree,"Harrison");
443: HTBTree_add(tree,"WWW");
444: wagazou = HTBTree_next(tree,NULL);
445: while (wagazou != NULL)
446: {
447: printf("The next element is %s\n",wagazou->object);
448: wagazou = HTBTree_next(tree,wagazou);
449: }
450: HTBTree_free (tree);
451: }
452:
453:
454: #endif
Webmaster