1: /* tree.h -- AVL trees (in the spirit of BSD's 'queue.h') -*- C -*- */
2:
3: /* Copyright (c) 2005 Ian Piumarta
4: *
5: * All rights reserved.
6: *
7: * Permission is hereby granted, free of charge, to any person obtaining a copy
8: * of this software and associated documentation files (the 'Software'), to deal
9: * in the Software without restriction, including without limitation the rights
10: * to use, copy, modify, merge, publish, distribute, and/or sell copies of the
11: * Software, and to permit persons to whom the Software is furnished to do so,
12: * provided that the above copyright notice(s) and this permission notice appear
13: * in all copies of the Software and that both the above copyright notice(s) and
14: * this permission notice appear in supporting documentation.
15: *
16: * THE SOFTWARE IS PROVIDED 'AS IS'. USE ENTIRELY AT YOUR OWN RISK.
17: */
18:
19: /* This file defines an AVL balanced binary tree [Georgii M. Adelson-Velskii and
20: * Evgenii M. Landis, 'An algorithm for the organization of information',
21: * Doklady Akademii Nauk SSSR, 146:263-266, 1962 (Russian). Also in Myron
22: * J. Ricci (trans.), Soviet Math, 3:1259-1263, 1962 (English)].
23: *
24: * An AVL tree is headed by pointers to the root node and to a function defining
25: * the ordering relation between nodes. Each node contains an arbitrary payload
26: * plus three fields per tree entry: the depth of the subtree for which it forms
27: * the root and two pointers to child nodes (singly-linked for minimum space, at
28: * the expense of direct access to the parent node given a pointer to one of the
29: * children). The tree is rebalanced after every insertion or removal. The
30: * tree may be traversed in two directions: forward (in-order left-to-right) and
31: * reverse (in-order, right-to-left).
32: *
33: * Because of the recursive nature of many of the operations on trees it is
34: * necessary to define a number of helper functions for each type of tree node.
35: * The macro TREE_DEFINE(node_tag, entry_name) defines these functions with
36: * unique names according to the node_tag. This macro should be invoked,
37: * thereby defining the necessary functions, once per node tag in the program.
38: *
39: * For details on the use of these macros, see the tree(3) manual page.
40: */
41:
42: #ifndef __tree_h
43: #define __tree_h
44:
45:
46: #define TREE_DELTA_MAX 1
47:
48: #define TREE_ENTRY(type) \
49: struct { \
50: struct type *avl_left; \
51: struct type *avl_right; \
52: int avl_height; \
53: }
54:
55: #define TREE_HEAD(name, type) \
56: struct name { \
57: struct type *th_root; \
58: int (*th_cmp)(struct type *lhs, struct type *rhs); \
59: }
60:
61: #define TREE_INITIALIZER(cmp) { 0, cmp }
62:
63: #define TREE_DELTA(self, field) \
64: (( (((self)->field.avl_left) ? (self)->field.avl_left->field.avl_height : 0)) \
65: - (((self)->field.avl_right) ? (self)->field.avl_right->field.avl_height : 0))
66:
67: /* Recursion prevents the following from being defined as macros. */
68:
69: #define TREE_DEFINE(node, field) \
70: \
71: struct node *TREE_BALANCE_##node##_##field(struct node *); \
72: \
73: struct node *TREE_ROTL_##node##_##field(struct node *self) \
74: { \
75: struct node *r= self->field.avl_right; \
76: self->field.avl_right= r->field.avl_left; \
77: r->field.avl_left= TREE_BALANCE_##node##_##field(self); \
78: return TREE_BALANCE_##node##_##field(r); \
79: } \
80: \
81: struct node *TREE_ROTR_##node##_##field(struct node *self) \
82: { \
83: struct node *l= self->field.avl_left; \
84: self->field.avl_left= l->field.avl_right; \
85: l->field.avl_right= TREE_BALANCE_##node##_##field(self); \
86: return TREE_BALANCE_##node##_##field(l); \
87: } \
88: \
89: struct node *TREE_BALANCE_##node##_##field(struct node *self) \
90: { \
91: int delta= TREE_DELTA(self, field); \
92: \
93: if (delta < -TREE_DELTA_MAX) \
94: { \
95: if (TREE_DELTA(self->field.avl_right, field) > 0) \
96: self->field.avl_right= TREE_ROTR_##node##_##field(self->field.avl_right); \
97: return TREE_ROTL_##node##_##field(self); \
98: } \
99: else if (delta > TREE_DELTA_MAX) \
100: { \
101: if (TREE_DELTA(self->field.avl_left, field) < 0) \
102: self->field.avl_left= TREE_ROTL_##node##_##field(self->field.avl_left); \
103: return TREE_ROTR_##node##_##field(self); \
104: } \
105: self->field.avl_height= 0; \
106: if (self->field.avl_left && (self->field.avl_left->field.avl_height > self->field.avl_height)) \
107: self->field.avl_height= self->field.avl_left->field.avl_height; \
108: if (self->field.avl_right && (self->field.avl_right->field.avl_height > self->field.avl_height)) \
109: self->field.avl_height= self->field.avl_right->field.avl_height; \
110: self->field.avl_height += 1; \
111: return self; \
112: } \
113: \
114: struct node *TREE_INSERT_##node##_##field \
115: (struct node *self, struct node *elm, int (*compare)(struct node *lhs, struct node *rhs)) \
116: { \
117: if (!self) \
118: return elm; \
119: if (compare(elm, self) < 0) \
120: self->field.avl_left= TREE_INSERT_##node##_##field(self->field.avl_left, elm, compare); \
121: else \
122: self->field.avl_right= TREE_INSERT_##node##_##field(self->field.avl_right, elm, compare); \
123: return TREE_BALANCE_##node##_##field(self); \
124: } \
125: \
126: struct node *TREE_FIND_##node##_##field \
127: (struct node *self, struct node *elm, int (*compare)(struct node *lhs, struct node *rhs)) \
128: { \
129: if (!self) \
130: return 0; \
131: if (compare(elm, self) == 0) \
132: return self; \
133: if (compare(elm, self) < 0) \
134: return TREE_FIND_##node##_##field(self->field.avl_left, elm, compare); \
135: else \
136: return TREE_FIND_##node##_##field(self->field.avl_right, elm, compare); \
137: } \
138: \
139: struct node *TREE_MOVE_RIGHT(struct node *self, struct node *rhs) \
140: { \
141: if (!self) \
142: return rhs; \
143: self->field.avl_right= TREE_MOVE_RIGHT(self->field.avl_right, rhs); \
144: return TREE_BALANCE_##node##_##field(self); \
145: } \
146: \
147: struct node *TREE_REMOVE_##node##_##field \
148: (struct node *self, struct node *elm, int (*compare)(struct node *lhs, struct node *rhs)) \
149: { \
150: if (!self) return 0; \
151: \
152: if (compare(elm, self) == 0) \
153: { \
154: struct node *tmp= TREE_MOVE_RIGHT(self->field.avl_left, self->field.avl_right); \
155: self->field.avl_left= 0; \
156: self->field.avl_right= 0; \
157: return tmp; \
158: } \
159: if (compare(elm, self) < 0) \
160: self->field.avl_left= TREE_REMOVE_##node##_##field(self->field.avl_left, elm, compare); \
161: else \
162: self->field.avl_right= TREE_REMOVE_##node##_##field(self->field.avl_right, elm, compare); \
163: return TREE_BALANCE_##node##_##field(self); \
164: } \
165: \
166: void TREE_FORWARD_APPLY_ALL_##node##_##field \
167: (struct node *self, void (*function)(struct node *node, void *data), void *data) \
168: { \
169: if (self) \
170: { \
171: TREE_FORWARD_APPLY_ALL_##node##_##field(self->field.avl_left, function, data); \
172: function(self, data); \
173: TREE_FORWARD_APPLY_ALL_##node##_##field(self->field.avl_right, function, data); \
174: } \
175: } \
176: \
177: void TREE_REVERSE_APPLY_ALL_##node##_##field \
178: (struct node *self, void (*function)(struct node *node, void *data), void *data) \
179: { \
180: if (self) \
181: { \
182: TREE_REVERSE_APPLY_ALL_##node##_##field(self->field.avl_right, function, data); \
183: function(self, data); \
184: TREE_REVERSE_APPLY_ALL_##node##_##field(self->field.avl_left, function, data); \
185: } \
186: }
187:
188: #define TREE_INSERT(head, node, field, elm) \
189: ((head)->th_root= TREE_INSERT_##node##_##field((head)->th_root, (elm), (head)->th_cmp))
190:
191: #define TREE_FIND(head, node, field, elm) \
192: (TREE_FIND_##node##_##field((head)->th_root, (elm), (head)->th_cmp))
193:
194: #define TREE_REMOVE(head, node, field, elm) \
195: ((head)->th_root= TREE_REMOVE_##node##_##field((head)->th_root, (elm), (head)->th_cmp))
196:
197: #define TREE_DEPTH(head, field) \
198: ((head)->th_root->field.avl_height)
199:
200: #define TREE_FORWARD_APPLY(head, node, field, function, data) \
201: TREE_FORWARD_APPLY_ALL_##node##_##field((head)->th_root, function, data)
202:
203: #define TREE_REVERSE_APPLY(head, node, field, function, data) \
204: TREE_REVERSE_APPLY_ALL_##node##_##field((head)->th_root, function, data)
205:
206: #define TREE_INIT(head, cmp) do { \
207: (head)->th_root= 0; \
208: (head)->th_cmp= (cmp); \
209: } while (0)
210:
211:
212: #endif /* __tree_h */
test.c
1: #include "tree.h"
2:
3: #include <stdio.h>
4: #include <stdlib.h>
5:
6: #define xnew(T) ((T *)calloc(1, sizeof(T)))
7: #define xfree(P) (free(P))
8:
9: typedef struct _Node Node;
10:
11: struct _Node
12: {
13: int key;
14: int value;
15: TREE_ENTRY(_Node) tree;
16: };
17:
18: Node *Node_new(int key, int value)
19: {
20: Node *self= xnew(Node);
21: self->key= key;
22: self->value= value;
23: return self;
24: }
25:
26: int Node_compare(Node *lhs, Node *rhs)
27: {
28: return rhs->key - lhs->key;
29: }
30:
31: void Node_print(Node *self, FILE *stream)
32: {
33: fprintf(stream, "%d is #%d", self->key, self->value);
34: }
35:
36: void Node_printer(Node *self, void *stream)
37: {
38: Node_print(self, (FILE *)stream);
39: fprintf((FILE *)stream, " ");
40: }
41:
42: // ----------------------------------------------------------------
43:
44: typedef TREE_HEAD(_Tree, _Node) Tree;
45:
46: TREE_DEFINE(_Node, tree);
47:
48: Tree *Tree_new(int (*compare)(Node *lhs, Node *rhs))
49: {
50: Tree *self= xnew(Tree);
51: TREE_INIT(self, compare);
52: return self;
53: }
54:
55: // ----------------------------------------------------------------
56:
57: #include "mersenne.h"
58:
59: int main(int argc, char **argv)
60: {
61: int i;
62: Tree tree= TREE_INITIALIZER(Node_compare);
63:
64: mt_random_init();
65:
66: for (i= 0; i < 100; ++i)
67: {
68: Node v= { mt_random() % 1000, i };
69: Node *vv= TREE_FIND(&tree, _Node, tree, &v);
70: if (vv)
71: {
72: printf("already inserted ");
73: Node_print(vv, stdout);
74: printf("\n");
75: }
76: else
77: {
78: printf("insert " );
79: Node_print(&v, stdout);
80: printf("\n");
81: TREE_INSERT(&tree, _Node, tree, Node_new(v.key, v.value));
82: TREE_FORWARD_APPLY(&tree, _Node, tree, Node_printer, stdout);
83: printf("\n");
84: }
85: }
86:
87: TREE_FORWARD_APPLY(&tree, _Node, tree, Node_printer, stdout);
88: printf("\n");
89:
90: for (i= 0; i < 1000; ++i)
91: {
92: Node *v= Node_new(mt_random() % 1000, 0);
93: Node *vv= TREE_FIND(&tree, _Node, tree, v);
94:
95: printf("looking for %d - ", v->key);
96: if (vv)
97: {
98: printf("found ");
99: Node_print(vv, stdout);
100: printf("\n");
101: TREE_FORWARD_APPLY(&tree, _Node, tree, Node_printer, stdout);
102: printf("\n");
103: }
104: else
105: {
106: printf("not found\n");
107: }
108: TREE_REMOVE(&tree, _Node, tree, v);
109: }
110:
111: TREE_FORWARD_APPLY(&tree, _Node, tree, Node_printer, stdout);
112: printf("\n");
113:
114: return 0;
115: }
test2.c
1: #include "tree.h"
2:
3: #include <stdio.h>
4: #include <stdlib.h>
5: #include <string.h>
6:
7: typedef struct _Node
8: {
9: char *word;
10: TREE_ENTRY(_Node) linkage;
11: } Node;
12:
13: typedef TREE_HEAD(_Tree, _Node) Tree;
14:
15: TREE_DEFINE(_Node, linkage);
16:
17: int fence = 0;
18:
19: Node *Node_new(char *word)
20: {
21: Node *self = (Node *)calloc(1, sizeof(Node));
22: self->word = strdup(word);
23: return self;
24: }
25:
26: int Node_compare(Node *lhs, Node *rhs)
27: {
28: return strcmp(lhs->word, rhs->word);
29: }
30:
31: void Node_print(Node *self, FILE *stream)
32: {
33: fprintf(stream, "%s", self->word);
34: }
35:
36: void Node_printer(Node *self, void *stream)
37: {
38: if (fence)
39: {
40: Node_print(self, (FILE *)stream);
41: --fence;
42: }
43: }
44:
45: int main(int argc, char **argv)
46: {
47: int count = 0;
48: Tree tree = TREE_INITIALIZER(Node_compare);
49: char line[80];
50:
51: while (fgets(line, sizeof(line), stdin))
52: {
53: Node test = { line };
54: Node *ptr = TREE_FIND(&tree, _Node, linkage, &test);
55: if (ptr)
56: printf("ignoring duplicate line: %s", line);
57: else
58: {
59: TREE_INSERT(&tree, _Node, linkage, Node_new(line));
60: ++count;
61: }
62: }
63:
64: fence = 20;
65: printf("first %d elements, forwards:\n", fence);
66: TREE_FORWARD_APPLY(&tree, _Node, linkage, Node_printer, stdout);
67: printf("\n");
68:
69: fence = 20;
70: printf("last %d elements, backwards:\n", fence);
71: TREE_REVERSE_APPLY(&tree, _Node, linkage, Node_printer, stdout);
72: printf("\n");
73:
74: printf("inserted %d elements into a tree of depth %d\n", count, TREE_DEPTH(&tree, linkage));
75:
76: return 0;
77: }