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 7246 2007-01-29 18:49:05Z twisti $
36 #include "mm/memory.h"
37 #include "toolbox/avl.h"
39 #if defined(ENABLE_THREADS)
40 # include "threads/native/lock.h"
42 # include "threads/none/lock.h"
46 /* avl_create ******************************************************************
48 Creates a AVL tree structure.
50 *******************************************************************************/
52 avl_tree *avl_create(avl_comparator *compar)
59 t->comparator = compar;
62 #if defined(ENABLE_THREADS)
63 /* create lock object for this tree */
65 t->lock = NEW(java_objectheader);
67 lock_init_object_lock(t->lock);
74 /* avl_newnode *****************************************************************
76 Creates a new AVL node and sets the pointers correctly.
78 *******************************************************************************/
80 static avl_node *avl_newnode(void *data)
88 /* ATTENTION: NEW allocates memory zeroed out */
91 /* n->childs[0] = NULL; */
92 /* n->childs[1] = NULL; */
98 /* avl_rotate_left *************************************************************
100 Does a left rotation on an AVL node.
108 *******************************************************************************/
110 static void avl_rotate_left(avl_node **node)
115 /* rotate the node */
118 tmpnode = tmp->childs[AVL_RIGHT];
119 tmp->childs[AVL_RIGHT] = tmpnode->childs[AVL_LEFT];
120 tmpnode->childs[AVL_LEFT] = tmp;
122 /* set new parent node */
128 /* avl_rotate_right ************************************************************
130 Does a right rotation on an AVL node.
138 *******************************************************************************/
140 static void avl_rotate_right(avl_node **node)
145 /* rotate the node */
148 tmpnode = tmp->childs[AVL_LEFT];
149 tmp->childs[AVL_LEFT] = tmpnode->childs[AVL_RIGHT];
150 tmpnode->childs[AVL_RIGHT] = tmp;
152 /* set new parent node */
158 /* avl_adjust_balance **********************************************************
160 Does a balance adjustment after a double rotation.
162 *******************************************************************************/
164 static void avl_adjust_balance(avl_node *node)
169 left = node->childs[AVL_LEFT];
170 right = node->childs[AVL_RIGHT];
172 switch (node->balance) {
193 /* avl_insert_intern ***********************************************************
195 Inserts a AVL node into a AVL tree.
197 *******************************************************************************/
199 static s4 avl_insert_intern(avl_tree *tree, avl_node **node, void *data)
207 /* set temporary variable */
211 /* per default no node was inserted */
215 /* compare the current node */
217 res = tree->comparator(data, tmpnode->data);
219 /* is this node already in the tree? */
224 /* goto left or right child */
226 direction = (res < 0) ? AVL_LEFT : AVL_RIGHT;
228 /* there is a child, go recursive */
230 if (tmpnode->childs[direction]) {
231 balance = avl_insert_intern(tree, &tmpnode->childs[direction], data);
236 /* no child, create this node */
238 newnode = avl_newnode(data);
240 /* insert into parent node */
242 tmpnode->childs[direction] = newnode;
244 /* node was inserted, but don't set insert to 1, since this
245 insertion is handled in this recursion depth */
250 /* add insertion value to node balance, value depends on the
253 tmpnode->balance += (direction == AVL_LEFT) ? -balance : balance;
255 if ((balance != 0) && (tmpnode->balance != 0)) {
256 if (tmpnode->balance < -1) {
257 /* left subtree too tall: right rotation needed */
259 if (tmpnode->childs[AVL_LEFT]->balance < 0) {
260 avl_rotate_right(&tmpnode);
262 /* simple balance adjustments */
264 tmpnode->balance = 0;
265 tmpnode->childs[AVL_RIGHT]->balance = 0;
268 avl_rotate_left(&tmpnode->childs[AVL_LEFT]);
269 avl_rotate_right(&tmpnode);
270 avl_adjust_balance(tmpnode);
273 } else if (tmpnode->balance > 1) {
274 /* right subtree too tall: left rotation needed */
276 if (tmpnode->childs[AVL_RIGHT]->balance > 0) {
277 avl_rotate_left(&tmpnode);
279 /* simple balance adjustments */
281 tmpnode->balance = 0;
282 tmpnode->childs[AVL_LEFT]->balance = 0;
285 avl_rotate_right(&tmpnode->childs[AVL_RIGHT]);
286 avl_rotate_left(&tmpnode);
287 avl_adjust_balance(tmpnode);
299 /* insertion was ok */
305 /* avl_insert ******************************************************************
307 Inserts a AVL node into a AVL tree.
309 *******************************************************************************/
311 bool avl_insert(avl_tree *tree, void *data)
316 LOCK_MONITOR_ENTER(tree->lock);
318 /* if we don't have a root node, create one */
320 if (tree->root == NULL) {
321 tree->root = avl_newnode(data);
324 avl_insert_intern(tree, &tree->root, data);
327 /* increase entries count */
332 printf("tree=%p entries=%d\n", tree, tree->entries);
334 printf("-------------------\n");
335 avl_dump(tree->root, 0);
336 printf("-------------------\n");
339 LOCK_MONITOR_EXIT(tree->lock);
341 /* insertion was ok */
347 /* avl_find ********************************************************************
349 Find a given data structure in the AVL tree, with the comparision
350 function of the tree.
352 *******************************************************************************/
354 void *avl_find(avl_tree *tree, void *data)
362 LOCK_MONITOR_ENTER(tree->lock);
364 /* search the tree for the given node */
366 for (node = tree->root; node != NULL; ) {
367 /* compare the current node */
369 res = tree->comparator(data, node->data);
371 /* was the entry found? return it */
374 LOCK_MONITOR_EXIT(tree->lock);
379 /* goto left or right child */
381 node = node->childs[(res < 0) ? AVL_LEFT : AVL_RIGHT];
384 LOCK_MONITOR_EXIT(tree->lock);
386 /* entry was not found, returning NULL */
392 /* avl_dump ********************************************************************
394 Dumps the AVL tree starting with node.
396 *******************************************************************************/
399 void avl_dump(avl_node* node, s4 indent)
408 if (node->childs[AVL_RIGHT])
409 avl_dump(node->childs[AVL_RIGHT], tmp + 1);
414 printf("%p (%d)\n", node->data, node->balance);
416 if (node->childs[AVL_LEFT])
417 avl_dump(node->childs[AVL_LEFT], tmp + 1);
423 * These are local overrides for various environment variables in Emacs.
424 * Please do not remove this and leave it at the end of the file, where
425 * Emacs will automagically detect them.
426 * ---------------------------------------------------------------------
429 * indent-tabs-mode: t