1 /* src/toolbox/avl.c - AVL tree implementation
3 Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 $Id: avl.c 7860 2007-05-03 12:30:05Z twisti $
36 #include "mm/memory.h"
38 #include "threads/lock-common.h"
40 #include "toolbox/avl.h"
43 /* avl_create ******************************************************************
45 Creates a AVL tree structure.
47 *******************************************************************************/
49 avl_tree_t *avl_create(avl_comparator *comparator)
56 t->comparator = comparator;
59 #if defined(ENABLE_THREADS)
60 /* create lock object for this tree */
62 t->lock = NEW(java_objectheader);
64 LOCK_INIT_OBJECT_LOCK(t->lock);
71 /* avl_newnode *****************************************************************
73 Creates a new AVL node and sets the pointers correctly.
75 *******************************************************************************/
77 static avl_node_t *avl_newnode(void *data)
85 /* ATTENTION: NEW allocates memory zeroed out */
88 /* n->childs[0] = NULL; */
89 /* n->childs[1] = NULL; */
95 /* avl_rotate_left *************************************************************
97 Does a left rotation on an AVL node.
105 *******************************************************************************/
107 static void avl_rotate_left(avl_node_t **node)
112 /* rotate the node */
115 tmpnode = tmp->childs[AVL_RIGHT];
116 tmp->childs[AVL_RIGHT] = tmpnode->childs[AVL_LEFT];
117 tmpnode->childs[AVL_LEFT] = tmp;
119 /* set new parent node */
125 /* avl_rotate_right ************************************************************
127 Does a right rotation on an AVL node.
135 *******************************************************************************/
137 static void avl_rotate_right(avl_node_t **node)
142 /* rotate the node */
145 tmpnode = tmp->childs[AVL_LEFT];
146 tmp->childs[AVL_LEFT] = tmpnode->childs[AVL_RIGHT];
147 tmpnode->childs[AVL_RIGHT] = tmp;
149 /* set new parent node */
155 /* avl_adjust_balance **********************************************************
157 Does a balance adjustment after a double rotation.
159 *******************************************************************************/
161 static void avl_adjust_balance(avl_node_t *node)
166 left = node->childs[AVL_LEFT];
167 right = node->childs[AVL_RIGHT];
169 switch (node->balance) {
190 /* avl_insert_intern ***********************************************************
192 Inserts a AVL node into a AVL tree.
194 *******************************************************************************/
196 static s4 avl_insert_intern(avl_tree_t *tree, avl_node_t **node, void *data)
204 /* set temporary variable */
208 /* per default no node was inserted */
212 /* compare the current node */
214 res = tree->comparator(tmpnode->data, data);
216 /* is this node already in the tree? */
221 /* goto left or right child */
223 direction = (res < 0) ? AVL_LEFT : AVL_RIGHT;
225 /* there is a child, go recursive */
227 if (tmpnode->childs[direction]) {
228 balance = avl_insert_intern(tree, &tmpnode->childs[direction], data);
233 /* no child, create this node */
235 newnode = avl_newnode(data);
237 /* insert into parent node */
239 tmpnode->childs[direction] = newnode;
241 /* node was inserted, but don't set insert to 1, since this
242 insertion is handled in this recursion depth */
247 /* add insertion value to node balance, value depends on the
250 tmpnode->balance += (direction == AVL_LEFT) ? -balance : balance;
252 if ((balance != 0) && (tmpnode->balance != 0)) {
253 if (tmpnode->balance < -1) {
254 /* left subtree too tall: right rotation needed */
256 if (tmpnode->childs[AVL_LEFT]->balance < 0) {
257 avl_rotate_right(&tmpnode);
259 /* simple balance adjustments */
261 tmpnode->balance = 0;
262 tmpnode->childs[AVL_RIGHT]->balance = 0;
265 avl_rotate_left(&tmpnode->childs[AVL_LEFT]);
266 avl_rotate_right(&tmpnode);
267 avl_adjust_balance(tmpnode);
270 } else if (tmpnode->balance > 1) {
271 /* right subtree too tall: left rotation needed */
273 if (tmpnode->childs[AVL_RIGHT]->balance > 0) {
274 avl_rotate_left(&tmpnode);
276 /* simple balance adjustments */
278 tmpnode->balance = 0;
279 tmpnode->childs[AVL_LEFT]->balance = 0;
282 avl_rotate_right(&tmpnode->childs[AVL_RIGHT]);
283 avl_rotate_left(&tmpnode);
284 avl_adjust_balance(tmpnode);
296 /* insertion was ok */
302 /* avl_insert ******************************************************************
304 Inserts a AVL node into a AVL tree.
306 *******************************************************************************/
308 bool avl_insert(avl_tree_t *tree, void *data)
313 LOCK_MONITOR_ENTER(tree->lock);
315 /* if we don't have a root node, create one */
317 if (tree->root == NULL) {
318 tree->root = avl_newnode(data);
321 avl_insert_intern(tree, &tree->root, data);
324 /* increase entries count */
329 printf("tree=%p entries=%d\n", tree, tree->entries);
331 printf("-------------------\n");
332 avl_dump(tree->root, 0);
333 printf("-------------------\n");
336 LOCK_MONITOR_EXIT(tree->lock);
338 /* insertion was ok */
344 /* avl_find ********************************************************************
346 Find a given data structure in the AVL tree, with the comparision
347 function of the tree.
349 *******************************************************************************/
351 void *avl_find(avl_tree_t *tree, void *data)
359 LOCK_MONITOR_ENTER(tree->lock);
361 /* search the tree for the given node */
363 for (node = tree->root; node != NULL; ) {
364 /* compare the current node */
366 res = tree->comparator(node->data, data);
368 /* was the entry found? return it */
371 LOCK_MONITOR_EXIT(tree->lock);
376 /* goto left or right child */
378 node = node->childs[(res < 0) ? AVL_LEFT : AVL_RIGHT];
381 LOCK_MONITOR_EXIT(tree->lock);
383 /* entry was not found, returning NULL */
389 /* avl_dump ********************************************************************
391 Dumps the AVL tree starting with node.
393 *******************************************************************************/
396 void avl_dump(avl_node_t* node, s4 indent)
405 if (node->childs[AVL_RIGHT])
406 avl_dump(node->childs[AVL_RIGHT], tmp + 1);
411 printf("%p (%d)\n", node->data, node->balance);
413 if (node->childs[AVL_LEFT])
414 avl_dump(node->childs[AVL_LEFT], tmp + 1);
420 * These are local overrides for various environment variables in Emacs.
421 * Please do not remove this and leave it at the end of the file, where
422 * Emacs will automagically detect them.
423 * ---------------------------------------------------------------------
426 * indent-tabs-mode: t