1 /* glpavl.c (binary search tree) */
3 /***********************************************************************
4 * This code is part of GLPK (GNU Linear Programming Kit).
6 * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
7 * 2009, 2010 Andrew Makhorin, Department for Applied Informatics,
8 * Moscow Aviation Institute, Moscow, Russia. All rights reserved.
9 * E-mail: <mao@gnu.org>.
11 * GLPK is free software: you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
16 * GLPK is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
19 * License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with GLPK. If not, see <http://www.gnu.org/licenses/>.
23 ***********************************************************************/
27 AVL *avl_create_tree(int (*fcmp)(void *info, const void *key1,
28 const void *key2), void *info)
29 { /* create AVL tree */
31 tree = xmalloc(sizeof(AVL));
32 tree->pool = dmp_create_pool();
41 int avl_strcmp(void *info, const void *key1, const void *key2)
42 { /* compare character string keys */
43 xassert(info == info);
44 return strcmp(key1, key2);
47 static AVLNODE *rotate_subtree(AVL *tree, AVLNODE *node);
49 AVLNODE *avl_insert_node(AVL *tree, const void *key)
50 { /* insert new node into AVL tree */
53 /* find an appropriate point for insertion */
54 p = NULL; q = tree->root;
57 if (tree->fcmp(tree->info, key, p->key) <= 0)
67 /* create new node and insert it into the tree */
68 r = dmp_get_atom(tree->pool, sizeof(AVLNODE));
69 r->key = key; r->type = 0; r->link = NULL;
70 r->rank = 1; r->up = p;
71 r->flag = (short int)(p == NULL ? 0 : flag);
72 r->bal = 0; r->left = NULL; r->right = NULL;
77 if (flag == 0) p->left = r; else p->right = r;
78 /* go upstairs to the root and correct all subtrees affected by
82 { /* the height of the left subtree of [p] is increased */
88 { rotate_subtree(tree, p);
91 p->bal = -1; flag = p->flag; p = p->up;
94 { /* the height of the right subtree of [p] is increased */
100 { rotate_subtree(tree, p);
103 p->bal = +1; flag = p->flag; p = p->up;
106 /* if the root has been reached, the height of the entire tree is
108 if (p == NULL) tree->height++;
112 void avl_set_node_type(AVLNODE *node, int type)
113 { /* assign the type field of specified node */
118 void avl_set_node_link(AVLNODE *node, void *link)
119 { /* assign the link field of specified node */
124 AVLNODE *avl_find_node(AVL *tree, const void *key)
125 { /* find node in AVL tree */
130 { c = tree->fcmp(tree->info, key, p->key);
132 p = (c < 0 ? p->left : p->right);
137 int avl_get_node_type(AVLNODE *node)
138 { /* retrieve the type field of specified node */
142 void *avl_get_node_link(AVLNODE *node)
143 { /* retrieve the link field of specified node */
147 static AVLNODE *find_next_node(AVL *tree, AVLNODE *node)
148 { /* find next node in AVL tree */
150 if (tree->root == NULL) return NULL;
152 q = (p == NULL ? tree->root : p->right);
154 { /* go upstairs from the left subtree */
157 if (q == NULL) break;
158 if (p->flag == 0) break;
163 { /* go downstairs into the right subtree */
166 if (p == NULL) break;
173 void avl_delete_node(AVL *tree, AVLNODE *node)
174 { /* delete specified node from AVL tree */
175 AVLNODE *f, *p, *q, *r, *s, *x, *y;
178 /* if both subtrees of the specified node are non-empty, the node
179 should be interchanged with the next one, at least one subtree
180 of which is always empty */
181 if (p->left == NULL || p->right == NULL) goto skip;
182 f = p->up; q = p->left;
183 r = find_next_node(tree, p); s = r->right;
188 if (p->flag == 0) f->left = r; else f->right = r;
189 r->rank = p->rank; r->up = f;
190 r->flag = p->flag; r->bal = p->bal;
191 r->left = q; r->right = p;
193 p->rank = 1; p->up = r; p->flag = 1;
194 p->bal = (short int)(s == NULL ? 0 : +1);
195 p->left = NULL; p->right = s;
196 if (s != NULL) s->up = p;
199 { x = p->right; y = r->up;
203 if (p->flag == 0) f->left = r; else f->right = r;
204 r->rank = p->rank; r->up = f;
205 r->flag = p->flag; r->bal = p->bal;
206 r->left = q; r->right = x;
207 q->up = r; x->up = r; y->left = p;
208 p->rank = 1; p->up = y; p->flag = 0;
209 p->bal = (short int)(s == NULL ? 0 : +1);
210 p->left = NULL; p->right = s;
211 if (s != NULL) s->up = p;
213 skip: /* now the specified node [p] has at least one empty subtree;
214 go upstairs to the root and adjust the rank field of all nodes
215 affected by deletion */
218 { if (q->flag == 0) f->rank--;
221 /* delete the specified node from the tree */
222 f = p->up; flag = p->flag;
223 q = p->left != NULL ? p->left : p->right;
227 if (flag == 0) f->left = q; else f->right = q;
228 if (q != NULL) q->up = f, q->flag = flag;
230 /* go upstairs to the root and correct all subtrees affected by
234 { /* the height of the left subtree of [f] is decreased */
242 { f = rotate_subtree(tree, f);
243 if (f->bal < 0) break;
245 flag = f->flag; f = f->up;
248 { /* the height of the right subtree of [f] is decreased */
256 { f = rotate_subtree(tree, f);
257 if (f->bal > 0) break;
259 flag = f->flag; f = f->up;
262 /* if the root has been reached, the height of the entire tree is
264 if (f == NULL) tree->height--;
265 /* returns the deleted node to the memory pool */
266 dmp_free_atom(tree->pool, p, sizeof(AVLNODE));
270 static AVLNODE *rotate_subtree(AVL *tree, AVLNODE *node)
271 { /* restore balance of AVL subtree */
272 AVLNODE *f, *p, *q, *r, *x, *y;
273 xassert(node != NULL);
276 { /* perform negative (left) rotation */
277 f = p->up; q = p->left; r = q->right;
279 { /* perform single negative rotation */
283 if (p->flag == 0) f->left = q; else f->right = q;
285 q->up = f; q->flag = p->flag; q->bal++; q->right = p;
286 p->up = q; p->flag = 1;
287 p->bal = (short int)(-q->bal); p->left = r;
288 if (r != NULL) r->up = p, r->flag = 0;
292 { /* perform double negative rotation */
293 x = r->left; y = r->right;
297 if (p->flag == 0) f->left = r; else f->right = r;
298 p->rank -= (q->rank + r->rank);
300 p->bal = (short int)(r->bal >= 0 ? 0 : +1);
301 q->bal = (short int)(r->bal <= 0 ? 0 : -1);
302 r->up = f; r->flag = p->flag; r->bal = 0;
303 r->left = q; r->right = p;
304 p->up = r; p->flag = 1; p->left = y;
305 q->up = r; q->flag = 0; q->right = x;
306 if (x != NULL) x->up = q, x->flag = 1;
307 if (y != NULL) y->up = p, y->flag = 0;
312 { /* perform positive (right) rotation */
313 f = p->up; q = p->right; r = q->left;
315 { /* perform single positive rotation */
319 if (p->flag == 0) f->left = q; else f->right = q;
321 q->up = f; q->flag = p->flag; q->bal--; q->left = p;
322 p->up = q; p->flag = 0;
323 p->bal = (short int)(-q->bal); p->right = r;
324 if (r != NULL) r->up = p, r->flag = 1;
328 { /* perform double positive rotation */
329 x = r->left; y = r->right;
333 if (p->flag == 0) f->left = r; else f->right = r;
336 p->bal = (short int)(r->bal <= 0 ? 0 : -1);
337 q->bal = (short int)(r->bal >= 0 ? 0 : +1);
338 r->up = f; r->flag = p->flag; r->bal = 0;
339 r->left = p; r->right = q;
340 p->up = r; p->flag = 0; p->right = x;
341 q->up = r; q->flag = 1; q->left = y;
342 if (x != NULL) x->up = p, x->flag = 1;
343 if (y != NULL) y->up = q, y->flag = 0;
350 void avl_delete_tree(AVL *tree)
351 { /* delete AVL tree */
352 dmp_delete_pool(tree->pool);