1 /* $Id: avl.cc,v 1.3 1994/06/24 10:59:08 ceriel Exp $ */
5 /* Implementation of AVL-trees: trees in which the difference in depth
6 of the left branch and the right branch is at most one.
7 The difference in depth is indicated by a "balance" flag in each node:
8 this flag has one of three values:
9 . indicating that the left branch has the same depth as the right branch,
10 + indicating that the right branch is deeper,
11 - indicating that the left branch is deeper.
12 So, a node has the following structure:
18 *right; /* the left and right branches */
19 char *info; /* pointer to information in this node */
20 char balance; /* balance information described above */
23 /* create definitions for new_avl_node() and free_avl_node() */
24 /* STATICALLOCDEF "avl_node" 10 */
26 /* There is also a tree header, which contains the root of the tree and
27 the address of a user-supplied comparison routine:
32 *root; /* root of the avl tree */
33 int (*cmp)(); /* address of comparison routine */
35 /* create definitions for new_avl_tree() and free_avl_tree() */
36 /* STATICALLOCDEF "avl_tree" 2 */
38 /* The next routine adds a node to an avl tree. It returns 1 if the
42 balance_add(ppsc, n, cmp)
43 struct avl_node **ppsc; /* address of root */
44 register char *n; /* user-supplied information */
45 int (*cmp)(); /* user-supplied comparison routine */
47 register struct avl_node *psc = *ppsc, *qsc, *ssc;
50 *ppsc = new_avl_node();
51 (*ppsc)->balance = '.';
55 if ((*cmp)(n, psc->info) < 0) {
56 if (balance_add(&(psc->left), n, cmp)) {
57 /* left hand side got deeper */
58 if (psc->balance == '+') {
59 /* but the right hand side was deeper */
63 if (psc->balance == '.') {
64 /* but the right hand side was as deep */
68 /* left hand side already was one deeper; re-organize */
70 if (qsc->balance == '-') {
71 /* if left-hand side of left node was deeper,
72 this node becomes the new root
76 psc->left = qsc->right;
81 /* else the right node of the left node becomes the new root */
83 psc->left = ssc->right;
84 qsc->right = ssc->left;
88 if (ssc->balance == '.') {
93 if (ssc->balance == '-') {
104 if (balance_add(&(psc->right), n, cmp)) {
105 /* right hand side got deeper */
106 if (psc->balance == '-') {
107 /* but the left hand side was deeper */
111 if (psc->balance == '.') {
112 /* but the left hand side as deep */
116 /* right hand side already was one deeper; re-organize */
118 if (qsc->balance == '+') {
119 /* if right-hand side of left node was deeper,
120 this node becomes the new root
124 psc->right = qsc->left;
129 /* else the left node of the right node becomes the new root */
131 psc->right = ssc->left;
132 qsc->left = ssc->right;
136 if (ssc->balance == '.') {
141 if (ssc->balance == '+') {
153 /* extern struct avl_tree *create_avl_tree(int (*cmp)());
154 Returns a fresh avl_tree structure.
158 int (*cmp)(); /* comparison routine */
160 register struct avl_tree *p = new_avl_tree();
166 /* extern add_to_avl_tree(struct avl_tree *tree, char *n);
167 Adds the information indicated by 'n' to the avl_tree indicated by 'tree'
169 add_to_avl_tree(tree, n)
170 struct avl_tree *tree; /* tree to be added to */
171 char *n; /* information */
173 (void) balance_add(&(tree->root), n, tree->cmp);
176 /* extern char *find_ngt(struct avl_tree *tree, char *n);
177 Returns the information in the largest node that still compares <= to 'n',
182 struct avl_tree *tree; /* tree to be searched in */
183 char *n; /* information to be compared with */
185 register struct avl_node *nd = tree->root, *lastnd = 0;
188 while (nd && (*tree->cmp)(nd->info, n) > 0) {
191 while (nd && (*tree->cmp)(nd->info, n) <= 0) {
197 return lastnd ? lastnd->info : (char *) 0;
200 /* extern char *find_nlt(struct avl_tree *tree, char *n);
201 Returns the information in the largest node that still compares >= to 'n',
206 struct avl_tree *tree; /* tree to be searched in */
207 char *n; /* information to be compared with */
209 register struct avl_node *nd = tree->root, *lastnd = 0;
212 while (nd && (*tree->cmp)(nd->info, n) < 0) {
215 while (nd && (*tree->cmp)(nd->info, n) >= 0) {
221 return lastnd ? lastnd->info : (char *) 0;
224 /* extern char *find_eq(struct avl_tree *tree, char *n);
225 Returns the information in the node that compares equal to 'n',
230 struct avl_tree *tree; /* tree to be searched in */
231 char *n; /* information to be compared with */
233 register struct avl_node *nd = tree->root;
236 while (nd && (*tree->cmp)(nd->info, n) < 0) {
239 while (nd && (*tree->cmp)(nd->info, n) > 0) {
244 return nd ? nd->info : (char *) 0;