home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
mitsch75.zip
/
scheme-7_5_17-src.zip
/
scheme-7.5.17
/
src
/
microcode
/
avltree.c
< prev
next >
Wrap
C/C++ Source or Header
|
2001-03-08
|
6KB
|
239 lines
/* -*-C-*-
$Id: avltree.c,v 1.5 2001/03/08 18:00:14 cph Exp $
Copyright (c) 1993-2001 Massachusetts Institute of Technology
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at
your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* This file contains the code for a simple AVL tree library.
It is used by the MIT Scheme microcode to quickly map
names to indices into various tables.
*/
#include "avltree.h"
extern int EXFUN (strcmp_ci, (CONST char * s1, CONST char * s2));
extern PTR EXFUN (malloc, (unsigned long));
extern void EXFUN (free, (PTR));
CONST char * tree_error_message = 0;
CONST char * tree_error_noise = 0;
static void
DEFUN (tree_error, (message, noise),
CONST char * message AND
CONST char * noise)
{
tree_error_message = message;
tree_error_noise = noise;
}
/* AVL trees. o(log n) lookup, insert (and delete, not implemented here).
AVL condition: for every node
abs (height (node.left) - height (node.right)) < 2
This guarantees that the least-balanced AVL tree has Fibonacci-sized
branches, and therefore the height is at most the log base phi of the
number of nodes, where phi is the golden ratio.
With random insertion (or when created as below),
they are better, approaching log base 2.
This version does not allow duplicate entries. */
#define BRANCH_HEIGHT(tree) (((tree) == 0) ? 0 : (tree)->height)
#ifndef MAX
# define MAX(a,b) (((a) >= (b)) ? (a) : (b))
#endif
static void
DEFUN (update_height, (tree), tree_node tree)
{
tree->height = (1 + (MAX ((BRANCH_HEIGHT (tree->left)),
(BRANCH_HEIGHT (tree->rite)))));
}
static tree_node
DEFUN (leaf_make, (name, value),
CONST char * name AND
unsigned long value)
{
tree_node leaf = ((tree_node) (malloc (sizeof (struct tree_node_s))));
if (leaf == 0)
{
tree_error ("leaf_make: malloc failed.\n", 0);
return (leaf);
}
leaf->name = name;
leaf->value = value;
leaf->height = 1;
leaf->left = 0;
leaf->rite = 0;
return (leaf);
}
static tree_node
DEFUN (rotate_left, (tree), tree_node tree)
{
tree_node rite = tree->rite;
tree_node beta = rite->left;
tree->rite = beta;
rite->left = tree;
update_height (tree);
update_height (rite);
return (rite);
}
static tree_node
DEFUN (rotate_rite, (tree), tree_node tree)
{
tree_node left = tree->left;
tree_node beta = left->rite;
tree->left = beta;
left->rite = tree;
update_height (tree);
update_height (left);
return (left);
}
static tree_node
DEFUN (rebalance_left, (tree), tree_node tree)
{
if ((1 + (BRANCH_HEIGHT (tree->rite))) >= (BRANCH_HEIGHT (tree->left)))
{
update_height (tree);
return (tree);
}
else
{
tree_node q = tree->left;
if ((BRANCH_HEIGHT (q->rite)) > (BRANCH_HEIGHT (q->left)))
tree->left = (rotate_left (q));
return (rotate_rite (tree));
}
}
static tree_node
DEFUN (rebalance_rite, (tree), tree_node tree)
{
if ((1 + (BRANCH_HEIGHT (tree->left))) >= (BRANCH_HEIGHT (tree->rite)))
{
update_height (tree);
return (tree);
}
else
{
tree_node q = tree->rite;
if ((BRANCH_HEIGHT (q->left)) > (BRANCH_HEIGHT (q->rite)))
tree->rite = (rotate_rite (q));
return (rotate_left (tree));
}
}
tree_node
DEFUN (tree_insert, (tree, name, value),
tree_node tree AND
CONST char * name AND
unsigned long value)
{
if (tree == 0)
return (leaf_make (name, value));
switch (strcmp_ci (name, tree->name))
{
case 0:
tree_error ("tree_insert: Duplicate entry %s.\n", name);
return (tree);
case -1:
{
/* To the left */
tree->left = (tree_insert (tree->left, name, value));
return (rebalance_left (tree));
}
case 1:
{
/* To the right */
tree->rite = (tree_insert (tree->rite, name, value));
return (rebalance_rite (tree));
}
}
/*NOTREACHED*/
return (0);
}
tree_node
DEFUN (tree_lookup, (tree, name), tree_node tree AND CONST char * name)
{
while (tree != 0)
switch (strcmp_ci (name, tree->name))
{
case 0:
return (tree);
case -1:
tree = tree->left;
break;
case 1:
tree = tree->rite;
break;
}
return (tree);
}
tree_node
DEFUN (tree_build, (high, names, value),
unsigned long high AND
CONST char ** names AND
unsigned long value)
{
static long bias = 0;
if (high > 1)
{
tree_node tree;
long middle = (high / 2);
long next;
if ((high & 1) == 0)
{
middle -= bias;
bias = (1 - bias);
}
next = (middle + 1);
tree = (leaf_make (names[middle], (value + middle)));
tree->left = (tree_build (middle, names, value));
tree->rite = (tree_build ((high - next), &names[next], (value + next)));
update_height (tree);
return (tree);
}
else if (high == 1)
return (leaf_make (* names, value));
else
return (0);
}
void
DEFUN (tree_free, (tree), tree_node tree)
{
if (tree != 0)
{
tree_free (tree->left);
tree_free (tree->rite);
free (tree);
}
}