avl.c revision 1.3 1 /* $NetBSD: avl.c,v 1.3 2002/03/21 05:15:39 phil Exp $ */
2
3 /*
4 * Copyright (c) 1997 Philip A. Nelson.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Philip A. Nelson.
18 * 4. The name of Philip A. Nelson may not be used to endorse or promote
19 * products derived from this software without specific prior written
20 * permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY PHILIP NELSON ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL PHILIP NELSON BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /* avl.c: Routines for manipulation an avl tree.
35 *
36 * an include file should define the following minimum struct.:
37 * (Comments must be made into real comments.)
38 *
39 * typedef struct id_rec {
40 * / * The balanced binary tree fields. * /
41 * char *id; / * The name. * /
42 * short balance; / * For the balanced tree. * /
43 * struct id_rec *left, *right; / * Tree pointers. * /
44 *
45 * / * Other information fields. * /
46 * } id_rec;
47 */
48
49 #include <string.h>
50
51 #include "defs.h"
52
53 /* find_id returns a pointer to node in TREE that has the correct
54 ID. If there is no node in TREE with ID, NULL is returned. */
55
56 id_rec *
57 find_id (id_rec *tree, char *id)
58 {
59 int cmp_result;
60
61 /* Check for an empty tree. */
62 if (tree == NULL)
63 return NULL;
64
65 /* Recursively search the tree. */
66 cmp_result = strcmp (id, tree->id);
67 if (cmp_result == 0)
68 return tree; /* This is the item. */
69 else if (cmp_result < 0)
70 return find_id (tree->left, id);
71 else
72 return find_id (tree->right, id);
73 }
74
75
76 /* insert_id inserts a NEW_ID rec into the tree whose ROOT is
77 provided. insert_id returns TRUE if the tree height from
78 ROOT down is increased otherwise it returns FALSE. This is a
79 recursive balanced binary tree insertion algorithm. */
80
81 int insert_id (id_rec **root, id_rec *new_id)
82 {
83 id_rec *A, *B;
84
85 /* If root is NULL, this where it is to be inserted. */
86 if (*root == NULL)
87 {
88 *root = new_id;
89 new_id->left = NULL;
90 new_id->right = NULL;
91 new_id->balance = 0;
92 return (TRUE);
93 }
94
95 /* We need to search for a leaf. */
96 if (strcmp (new_id->id, (*root)->id) < 0)
97 {
98 /* Insert it on the left. */
99 if (insert_id (&((*root)->left), new_id))
100 {
101 /* The height increased. */
102 (*root)->balance --;
103
104 switch ((*root)->balance)
105 {
106 case 0: /* no height increase. */
107 return (FALSE);
108 case -1: /* height increase. */
109 return (TRUE);
110 case -2: /* we need to do a rebalancing act. */
111 A = *root;
112 B = (*root)->left;
113 if (B->balance <= 0)
114 {
115 /* Single Rotate. */
116 A->left = B->right;
117 B->right = A;
118 *root = B;
119 A->balance = 0;
120 B->balance = 0;
121 }
122 else
123 {
124 /* Double Rotate. */
125 *root = B->right;
126 B->right = (*root)->left;
127 A->left = (*root)->right;
128 (*root)->left = B;
129 (*root)->right = A;
130 switch ((*root)->balance)
131 {
132 case -1:
133 A->balance = 1;
134 B->balance = 0;
135 break;
136 case 0:
137 A->balance = 0;
138 B->balance = 0;
139 break;
140 case 1:
141 A->balance = 0;
142 B->balance = -1;
143 break;
144 }
145 (*root)->balance = 0;
146 }
147 }
148 }
149 }
150 else
151 {
152 /* Insert it on the right. */
153 if (insert_id (&((*root)->right), new_id))
154 {
155 /* The height increased. */
156 (*root)->balance ++;
157 switch ((*root)->balance)
158 {
159 case 0: /* no height increase. */
160 return (FALSE);
161 case 1: /* height increase. */
162 return (TRUE);
163 case 2: /* we need to do a rebalancing act. */
164 A = *root;
165 B = (*root)->right;
166 if (B->balance >= 0)
167 {
168 /* Single Rotate. */
169 A->right = B->left;
170 B->left = A;
171 *root = B;
172 A->balance = 0;
173 B->balance = 0;
174 }
175 else
176 {
177 /* Double Rotate. */
178 *root = B->left;
179 B->left = (*root)->right;
180 A->right = (*root)->left;
181 (*root)->left = A;
182 (*root)->right = B;
183 switch ((*root)->balance)
184 {
185 case -1:
186 A->balance = 0;
187 B->balance = 1;
188 break;
189 case 0:
190 A->balance = 0;
191 B->balance = 0;
192 break;
193 case 1:
194 A->balance = -1;
195 B->balance = 0;
196 break;
197 }
198 (*root)->balance = 0;
199 }
200 }
201 }
202 }
203
204 /* If we fall through to here, the tree did not grow in height. */
205 return (FALSE);
206 }
207