home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
listings
/
v_09_06
/
9n06071a
< prev
next >
Wrap
Text File
|
1990-11-12
|
9KB
|
275 lines
/* Functions for optimizing a binary tree. A tree is optimized with a simple
call to function "optimize(root)".
*/
#include <stdio.h> /* Included only for compiler definition of NULL */
/* Flag values */
#define LEFT 1 /* Depth count/fold/"special" to the left */
#define RIGHT 0 /* Depth count/fold/"special" to the right */
/* Tree struct */
typedef struct tnode { /* Standard binary tree node for storage */
struct tnode *left, *right;
/* Data would go here, but not needed. */
} TREENODE;
static
TREENODE *worstroot, /* Pointer to worst-case root */
*temp_root; /* Traversal pointer */
/* Function prototypes */
void *optimize(void *); /* Optimize a tree */
static
TREENODE *fixbranch(TREENODE *, int), /* "Fix" a branch */
*fold(TREENODE *, int), /* "Fold" a branch */
*special(TREENODE *, int); /* Perform "special" optimization */
static
int depth(TREENODE *, int); /* Determine depth of a branch */
static
void worstcase(TREENODE *); /* Rebuild tree into worst-case */
/* Function to initiate the process of optimizing the tree. Optimization is
performed by rearranging a binary tree into its worst-case form and then
folding this new tree and any subtrees in half at any branch of a linear
length of 3 or more nodes.
Usage: void *optimize(opt_root)
void *opt_root; /* Root of a binary tree
Returns: A pointer to the optimized tree.
*/
void *optimize(opt_root)
void *opt_root;
{
int rdepth, ldepth; /* Depth of left & right subtrees */
TREENODE *root; /* Pointer to working root of tree */
if (opt_root == NULL)
return(NULL);
worstroot = temp_root = NULL;
/* Build worst-case tree. Root is in "worstroot" */
worstcase(opt_root);
root = worstroot;
/* Fold worst-case tree in half if three or more nodes */
if (depth(root, RIGHT) > 1)
root = fold(root, RIGHT);
/* Fold left and right subtrees if three or more nodes */
rdepth = depth(root, RIGHT);
ldepth = depth(root, LEFT);
if ((rdepth == 2) && (ldepth == 2))
root = special(root, RIGHT);
else
if ((rdepth > 2) || (ldepth > 2)) {
root = fixbranch(root, RIGHT);
root = fixbranch(root, LEFT);
}
return((void *) root);
}
/* Function to determine the right or left depth of a local root NOT INCLUDING
the local root itself.
Usage: int depth(node, dir)
TREENODE *node; /* Pointer to a local root
int dir; /* Direction (LEFT or RIGHT)
Returns: The depth of the local root.
*/
int depth(node, dir)
TREENODE *node;
int dir;
{
int d = 0; /* Depth count */
switch(dir) {
case RIGHT:
while (node->right != NULL) {
d++;
node = node->right;
}
break;
case LEFT:
while (node->left != NULL) {
d++;
node = node->left;
}
break;
default:
return(0);
}
return(d);
}
/* Function to handle a special optimization case at a local root.
3 4 2
/ \ / \ / \
2 4 changed to 2 5 or 1 4
/ \ / \ / \
1 5 1 3 3 5
Case 1 Case 2
This allows the section of the tree to remain in optimal form in the event
a number is added that is greater than 5 in the first case, or less than 1
in the second case.
Usage: TREENODE *special(node, dir)
TREENODE *node; /* Pointer to a local root
int dir; /* Direction to hang the majority of nodes
Returns: A pointer to the updated local root
*/
TREENODE *special(node, dir)
TREENODE *node;
int dir;
{
TREENODE *temp, /* Temporary pointer */
*newnode; /* Pointer to "specially" optimized subtree */
switch(dir) {
case RIGHT:
node->left->right = node;
temp = node->left;
newnode = node->right;
node->left = NULL;
node->right = NULL;
newnode->left = temp;
break;
case LEFT:
node->right->left = node;
temp = node->right;
newnode = node->left;
node->right = NULL;
node->left = NULL;
newnode->right = temp;
break;
default:
newnode = node;
break;
}
return(newnode);
}
/* Recursive function to initiate the folding of a worst-case local root
into its most optimal form.
Usage: TREENODE *fixbranch(node, dir)
TREENODE *node; /* Pointer to a local root
int dir; /* Direction to fix (LEFT or RIGHT)
Returns: A pointer to an updated local root
*/
TREENODE *fixbranch(node, dir)
TREENODE *node;
int dir;
{
switch(dir) {
case RIGHT:
/* Check for special case */
if ((depth(node, RIGHT) == 2) && (depth(node, LEFT) == 2))
node = special(node, dir);
else
/* Fold right subtree */
node->right = fold(node->right, RIGHT);
/* Fold new right subtree if three or more nodes including the root */
if (depth(node->right, RIGHT) > 1)
node->right = fixbranch(node->right, RIGHT);
/* Fold new left subtree if four or more nodes including the root */
if (depth(node->right, LEFT) > 2)
node->right = fixbranch(node->right, LEFT);
break;
case LEFT:
/* Check for special case */
if ((depth(node, LEFT) == 2) && (depth(node, RIGHT) == 2))
node = special(node, dir);
else
/* Fold left subtree */
node->left = fold(node->left, LEFT);
/* Fold new left subtree if three or more nodes including the root */
if (depth(node->left, LEFT) > 1)
node->left = fixbranch(node->left, LEFT);
/* fold new right subtree if four or more nodes including the root */
if (depth(node->left, RIGHT) > 2)
node->left = fixbranch(node->left, RIGHT);
break;
}
return(node);
}
/* Function to fold a branch of a local root in the direction given.
Usage: TREENODE *fold(node, dir)
TREENODE *node; /* Pointer to a local root
int dir; /* Direction to fold
Returns: A pointer to an updated local root
*/
TREENODE *fold(node, dir)
TREENODE *node;
int dir;
{
TREENODE *newroot, /* Pointer to folded branch */
*temproot; /* Temporary pointer */
int ndepth, /* Node depth */
loop; /* Looping variable */
switch(dir) {
case RIGHT:
ndepth = depth(node, RIGHT);
if (ndepth % 2)
ndepth++; /* Leave any overhang to the left */
ndepth >>= 1;
/* Current parent node becomes left child for all nodes from the first
node in the branch to the middle node */
for (loop = 0; loop < ndepth; loop++) {
node->right->left = node;
temproot = node->right;
node->right = NULL;
node = temproot;
}
break;
case LEFT:
ndepth = depth(node, LEFT);
if (ndepth % 2)
ndepth++; /* Leave any overhang to the left */
ndepth >>= 1;
/* Current parent node becomes right child for all nodes from the first
node in the branch to the middle node */
for (loop = 0; loop < ndepth; loop++) {
node->left->right = node;
temproot = node->left;
node->left = NULL;
node = temproot;
}
break;
default:
return(NULL);
break;
}
return(node);
}
/* Recursive fuction to rebuild a tree into its worst-case form. The root of
the worst-case tree is stored in the global variable "worstroot".
Usage: void worstcase(root)
TREENODE *root; /* Pointer to root of a tree
Returns: Nothing
*/
void worstcase(root)
TREENODE *root;
{
if (root != NULL) {
worstcase(root->left);
if (worstroot == NULL)
temp_root = worstroot = root;
else
temp_root->right = root;
root->left = NULL;
temp_root = root;
worstcase(root->right);
}
}