home *** CD-ROM | disk | FTP | other *** search
- /*
- digbtree.c
-
- % Binary tree manipulation code.
-
- OWL-DIG 1.2
- Copyright (c) 1990 by Oakland Group, Inc.
- ALL RIGHTS RESERVED.
-
- Revision History:
- -----------------
- 5/31/90 bkd Created.
- 8/14/90 bkd made btree_TreeInsert return a btreecode
- 9/24/90 jsm added cast for C++
- 10/03/90 ted added conditional code to work around Watcom compiler bug.
- */
-
- #include "oakhead.h"
- #include "disppriv.h"
- #include "digutil.h"
- /* -------------------------------------------------------------------------- */
-
- OSTATIC void DIGPRIV btree_TreeClose(btree_type bt, btnode_type node);
- OSTATIC btreecode DIGPRIV btree_TreeInsert(btree_type bt, btnode_type tree, VOID *data);
- OSTATIC VOID * DIGPRIV btree_TreeGet(btree_type bt, btnode_type tree, byte *key);
-
- /*
- A btree is a simple ordered binary tree. Associated with each
- btree are three routines:
- 1) The nodecomp routine. This routine compares any two nodes
- and provides a signed numeric value corresponding to
- less than, equal to or greater than.
- 2) The keycomp routine. This one is similar to the nodecomp
- routine except that instead being given two nodes, this
- one is fed a node and a pointer to a "key". The key is
- that part of a node which is used for these comparisons.
- 3) The freertn routine. At btree_Close time (and possibly
- during error recovery) a tree must be freed up. The node
- data pointers are (most likely) lost at this point. They are
- fed to the freertn before being cast into the void. Ugh.
- That last thing sounds like a nasty pun. I apologize.
- */
-
- /* -------------------------------------------------------------------------- */
- /********* CREATORS *********/
-
- btree_type DIGPRIV btree_Open(
- btree_nodecomp_fptr nodecomp,
- btree_keycomp_fptr keycomp,
- btree_freertn_fptr freertn)
- {
- register btree_type bt;
-
- if ((bt = (btree_type) omalloc(OA_BTREE, sizeof(* (btree_type) 0)))
- == NULL) {
- return(NULL);
- }
-
- bt->root = NULL;
- bt->nodecomp = nodecomp;
- bt->keycomp = keycomp;
- bt->freertn = freertn;
-
- return(bt);
- }
- /* -------------------------------------------------------------------------- */
- /********* DESTROYERS *********/
-
- void DIGPRIV btree_Close(btree_type bt)
- {
- if (bt == NULL) {
- return;
- }
- btree_TreeClose(bt, bt->root);
- }
- /* -------------------------------------------------------------------------- */
- /********* MUTATORS *********/
-
- btreecode DIGPRIV btree_Insert(btree_type bt, VOID *data)
- /*
- btree_Insert - Insert a hunk of data into a btree. Can return
- a number of values:
- BTREE_ERROR - An error occurred. Most likely this
- means that you ran out of memory.
- BTREE_DUP - A node was found that, according to the nodecomp
- routine, has the same weight as the new data.
- BTREE_OK - Data were inserted without incident.
- */
- {
- btnode_type node;
- btreecode rval;
-
- if (bt == NULL || data == NULL) {
- return(BTREE_ERROR);
- }
-
- node = bt->root;
- if (node == NULL) {
- #ifdef __WATCOMC__
- node = NULL; /* Just to avoid Watcom compiler crash */
- #endif
- if ((node = (btnode_type)
- omalloc(OA_BTREE, sizeof(* (btnode_type) 0))) == NULL) {
- return(BTREE_ERROR);
- }
- node->lchild = node->rchild = NULL;
- node->data = data;
-
- bt->root = node;
-
- rval = BTREE_OK;
- }
- else {
- rval = btree_TreeInsert(bt, bt->root, data);
- }
- return(rval);
- }
- /* -------------------------------------------------------------------------- */
- /********* OBSERVERS *********/
-
- VOID * DIGPRIV btree_Get(btree_type bt, VOID *key)
- {
- VOID *rval;
-
- if (bt == NULL || key == NULL) {
- return(NULL);
- }
- rval = btree_TreeGet(bt, bt->root, (byte *) key);
- return(rval);
- }
- /* -------------------------------------------------------------------------- */
- /* -------------------------------------------------------------------------- */
-
- static void DIGPRIV btree_TreeClose(btree_type bt, btnode_type node)
- /*
- (recursively) closes down nodes in a tree.
- */
- {
- if (node == NULL) {
- return;
- }
-
- /* Close down the children below this node */
-
- btree_TreeClose(bt, node->lchild);
- btree_TreeClose(bt, node->rchild);
-
- /* and now close this node proper. */
-
- (*bt->freertn)(node->data);
-
- ofree(OA_BTREE, (VOID *) node);
- }
- /* -------------------------------------------------------------------------- */
-
- static btreecode DIGPRIV btree_TreeInsert(btree_type bt, btnode_type tree, VOID *data)
- /*
- btree_TreeInsert - An internal recursive routine used by btree_Insert
- to insert a hunk of data.
- */
- {
- register int comparison;
- register btnode_type newnode;
- btnode_type *childp, tchild;
-
- comparison = (*bt->nodecomp)(tree->data, data);
-
- if (comparison == 0) {
- return(BTREE_DUP);
- }
- else if (comparison < 0) {
- childp = &(tree->rchild);
- }
- else {
- childp = &(tree->lchild);
- }
-
- tchild = *childp;
- if (tchild == NULL) {
- #ifdef __WATCOMC__
- tchild = NULL; /* Just to avoid Watcom compiler crash */
- #endif
- if ((newnode = (btnode_type)
- omalloc(OA_BTREE, sizeof(* (btnode_type) 0))) == NULL) {
- return(BTREE_ERROR);
- }
- newnode->lchild = newnode->rchild = NULL;
- newnode->data = data;
- *childp = newnode;
-
- return(BTREE_OK);
- }
- else {
- return(btree_TreeInsert(bt, *childp, data));
- }
- }
- /* -------------------------------------------------------------------------- */
-
- static VOID * DIGPRIV btree_TreeGet(btree_type bt, btnode_type tree, byte *key)
- {
- register int comparison;
- register btnode_type child;
-
- if (tree == NULL) {
- return(NULL);
- }
-
- comparison = (*bt->keycomp)(tree->data, key);
-
- if (comparison == 0) {
- return(tree->data);
- }
- else if (comparison < 0) {
- child = tree->rchild;
- }
- else {
- child = tree->lchild;
- }
-
- return(btree_TreeGet(bt, child, key));
- }
- /* -------------------------------------------------------------------------- */
-
-