Importing from busted CVS
commit
d10b87ef2b
|
@ -0,0 +1,306 @@
|
||||||
|
/*
|
||||||
|
* A free AVLTree implementation written by Andrew Coleman
|
||||||
|
* find out more cool things and licensing at http://penguincoder.org
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "Tree.h"
|
||||||
|
|
||||||
|
TreeNode *FindByElement(TreeNode *rootNode, Element Data)
|
||||||
|
{
|
||||||
|
short comp;
|
||||||
|
TreeNode *Return;
|
||||||
|
|
||||||
|
/* sanity checks */
|
||||||
|
if(Data == NULL)
|
||||||
|
return NULL;
|
||||||
|
else if(rootNode == NULL || rootNode->Item == NULL) {
|
||||||
|
/* reached a leaf, and the data was not found */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* non recursive search because it really isn't neccessary right here */
|
||||||
|
Return = rootNode;
|
||||||
|
do {
|
||||||
|
comp = Compare(Return->Item, Data);
|
||||||
|
if(comp < 0)
|
||||||
|
Return = Return->Left;
|
||||||
|
else if(comp > 0)
|
||||||
|
Return = Return->Right;
|
||||||
|
} while(Return != NULL && comp != 0);
|
||||||
|
return Return;
|
||||||
|
}
|
||||||
|
|
||||||
|
short IsEmpty(TreeNode *rootNode)
|
||||||
|
{
|
||||||
|
return (rootNode == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeNode *SingleRightRotation(TreeNode *rootNode)
|
||||||
|
{
|
||||||
|
TreeNode *newRoot = NULL;
|
||||||
|
newRoot = rootNode->Left;
|
||||||
|
rootNode->Left = newRoot->Right;
|
||||||
|
newRoot->Right = rootNode;
|
||||||
|
return newRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeNode *SingleLeftRotation(TreeNode *rootNode)
|
||||||
|
{
|
||||||
|
TreeNode *newRoot = NULL;
|
||||||
|
newRoot = rootNode->Right;
|
||||||
|
rootNode->Right = newRoot->Left;
|
||||||
|
newRoot->Left = rootNode;
|
||||||
|
return newRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeNode *DoubleRightRotation(TreeNode *rootNode)
|
||||||
|
{
|
||||||
|
TreeNode *newRoot = SingleLeftRotation(rootNode->Left);
|
||||||
|
rootNode->Left = newRoot;
|
||||||
|
newRoot = SingleRightRotation(rootNode);
|
||||||
|
return newRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeNode *DoubleLeftRotation(TreeNode *rootNode)
|
||||||
|
{
|
||||||
|
TreeNode *newRoot = SingleRightRotation(rootNode->Right);
|
||||||
|
rootNode->Right = newRoot;
|
||||||
|
newRoot = SingleLeftRotation(rootNode);
|
||||||
|
return newRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeNode *CheckTreeNodeRotation(TreeNode *tnode,
|
||||||
|
TreeNode *subtree, short *finished)
|
||||||
|
{
|
||||||
|
/* this function will check to see if tnode's Balance factor indicates
|
||||||
|
that a rotation is needed. Subtree is the child link that was either
|
||||||
|
just added or possibly changed */
|
||||||
|
switch(tnode->Balance) {
|
||||||
|
case 0:
|
||||||
|
/* nothing special, but we have balanced out properly, yay */
|
||||||
|
*finished = 1;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
/* right heavy */
|
||||||
|
*finished = 1;
|
||||||
|
if(subtree->Balance == -1) {
|
||||||
|
/* update balance factors */
|
||||||
|
if(subtree->Left->Balance == 1) {
|
||||||
|
subtree->Balance = 0;
|
||||||
|
tnode->Balance = -1;
|
||||||
|
} else if(subtree->Left->Balance == -1) {
|
||||||
|
subtree->Balance = 1;
|
||||||
|
tnode->Balance = 0;
|
||||||
|
} else
|
||||||
|
subtree->Balance = tnode->Balance = 0;
|
||||||
|
subtree->Left->Balance = 0;
|
||||||
|
tnode = DoubleLeftRotation(tnode);
|
||||||
|
} else if(subtree->Balance == 1) {
|
||||||
|
/* update balance factors */
|
||||||
|
subtree->Balance = tnode->Balance = 0;
|
||||||
|
tnode = SingleLeftRotation(tnode);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case -2:
|
||||||
|
/* left heavy */
|
||||||
|
*finished = 1;
|
||||||
|
if(subtree->Balance == 1) {
|
||||||
|
/* update balance factors */
|
||||||
|
if(subtree->Right->Balance == -1) {
|
||||||
|
subtree->Balance = 0;
|
||||||
|
tnode->Balance = 1;
|
||||||
|
} else if(subtree->Right->Balance == 1) {
|
||||||
|
subtree->Balance = -1;
|
||||||
|
tnode->Balance = 0;
|
||||||
|
} else
|
||||||
|
subtree->Balance = tnode->Balance = 0;
|
||||||
|
subtree->Right->Balance = 0;
|
||||||
|
tnode = DoubleRightRotation(tnode);
|
||||||
|
} else if(subtree->Balance == -1) {
|
||||||
|
/* update balance factors */
|
||||||
|
subtree->Balance = tnode->Balance = 0;
|
||||||
|
tnode = SingleRightRotation(tnode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tnode;
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeNode *InsertNode(TreeNode *tnode, Element Item,
|
||||||
|
char *Name, short *finished)
|
||||||
|
{
|
||||||
|
TreeNode *subtree = NULL;
|
||||||
|
short comp = 0;
|
||||||
|
|
||||||
|
if(tnode == NULL) {
|
||||||
|
/* found the spot that the TreeNode belongs */
|
||||||
|
tnode = malloc(sizeof(TreeNode));
|
||||||
|
/* malloc problem, return NULL */
|
||||||
|
if(tnode == NULL)
|
||||||
|
return NULL;
|
||||||
|
else {
|
||||||
|
/* default settings for a new node */
|
||||||
|
tnode->Left = NULL;
|
||||||
|
tnode->Right = NULL;
|
||||||
|
tnode->Item = Item;
|
||||||
|
tnode->Name = Name;
|
||||||
|
tnode->Balance = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* need to find the new node, don't check for a 0,
|
||||||
|
cos its already in teh tree, foo */
|
||||||
|
comp = Compare(Item, tnode->Item);
|
||||||
|
if(comp < 0) {
|
||||||
|
/* go left */
|
||||||
|
subtree = InsertNode(tnode->Left, Item, Name, finished);
|
||||||
|
/* if this is NULL, there is problem. quit now */
|
||||||
|
if(subtree == NULL)
|
||||||
|
return NULL;
|
||||||
|
/* you are not finished until Balance == 0, reached the root
|
||||||
|
or a rotation has occured */
|
||||||
|
if(!*finished)
|
||||||
|
tnode->Balance--;
|
||||||
|
tnode->Left = subtree;
|
||||||
|
} else if(comp > 0) {
|
||||||
|
/* go right */
|
||||||
|
subtree = InsertNode(tnode->Right, Item, Name, finished);
|
||||||
|
if(subtree == NULL)
|
||||||
|
return NULL;
|
||||||
|
if(!*finished)
|
||||||
|
tnode->Balance++;
|
||||||
|
tnode->Right = subtree;
|
||||||
|
} else
|
||||||
|
/* got a dupe, return NULL */
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* check if a rotation is neccessary */
|
||||||
|
if(!*finished) {
|
||||||
|
tnode = CheckTreeNodeRotation(tnode, subtree, finished);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tnode;
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeNode *Insert(TreeNode *tnode, Element Item, char *Name)
|
||||||
|
{
|
||||||
|
/* flag for the recursive function */
|
||||||
|
short done = 0;
|
||||||
|
/* run and return the recursive insert */
|
||||||
|
return InsertNode(tnode, Item, Name, &done);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MakeEmpty(TreeNode *rootNode)
|
||||||
|
{
|
||||||
|
/* this function is pretty simple, just traverses the tree and starts
|
||||||
|
free'ing from the bottom up */
|
||||||
|
if(rootNode == NULL)
|
||||||
|
return;
|
||||||
|
MakeEmpty(rootNode->Left);
|
||||||
|
MakeEmpty(rootNode->Right);
|
||||||
|
FreeElement(rootNode->Item);
|
||||||
|
free(rootNode->Name);
|
||||||
|
free(rootNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeNode *DeleteLeftMost(TreeNode **deletedNode, TreeNode *rootNode,
|
||||||
|
short *finished)
|
||||||
|
{
|
||||||
|
TreeNode *subtree = rootNode->Right;
|
||||||
|
if(rootNode == NULL) {
|
||||||
|
printf("bailing!\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if(rootNode->Left == NULL) {
|
||||||
|
free((*deletedNode)->Name);
|
||||||
|
FreeElement((*deletedNode)->Item);
|
||||||
|
(*deletedNode)->Name = rootNode->Name;
|
||||||
|
(*deletedNode)->Item = rootNode->Item;
|
||||||
|
free(rootNode);
|
||||||
|
rootNode = subtree;
|
||||||
|
} else {
|
||||||
|
rootNode->Left = DeleteLeftMost(deletedNode, rootNode->Left, finished);
|
||||||
|
if(!*finished) {
|
||||||
|
rootNode->Balance++;
|
||||||
|
if(rootNode->Left != NULL)
|
||||||
|
rootNode = CheckTreeNodeRotation(rootNode, rootNode->Left,
|
||||||
|
finished);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rootNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeNode *DeleteByElementRecursive(TreeNode *rootNode,
|
||||||
|
Element Item, short *finished)
|
||||||
|
{
|
||||||
|
TreeNode *subtree = NULL;
|
||||||
|
short comp = 0;
|
||||||
|
|
||||||
|
/* found a leaf */
|
||||||
|
if(rootNode == NULL)
|
||||||
|
return NULL;
|
||||||
|
/* figure out where the node in question is in relation to the current */
|
||||||
|
comp = Compare(rootNode->Item, Item);
|
||||||
|
if(comp > 0) {
|
||||||
|
/* buried somewhere in the right subtree */
|
||||||
|
subtree = DeleteByElementRecursive(rootNode->Right, Item, finished);
|
||||||
|
rootNode->Right = subtree;
|
||||||
|
if(!*finished && subtree != NULL) {
|
||||||
|
rootNode->Balance--;
|
||||||
|
rootNode = CheckTreeNodeRotation(rootNode, subtree, finished);
|
||||||
|
}
|
||||||
|
} else if(comp < 0) {
|
||||||
|
subtree = DeleteByElementRecursive(rootNode->Left, Item, finished);
|
||||||
|
rootNode->Left = subtree;
|
||||||
|
if(!*finished && subtree != NULL) {
|
||||||
|
rootNode->Balance++;
|
||||||
|
rootNode = CheckTreeNodeRotation(rootNode, subtree, finished);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* found what we were looking for */
|
||||||
|
if(rootNode->Right == NULL) {
|
||||||
|
/* rootNode is replaced by the left child; can be null */
|
||||||
|
subtree = rootNode->Left;
|
||||||
|
free(rootNode->Name);
|
||||||
|
FreeElement(rootNode->Item);
|
||||||
|
free(rootNode);
|
||||||
|
rootNode = subtree;
|
||||||
|
} else if(rootNode->Right->Left == NULL) {
|
||||||
|
/* rootNode is replaced by Right */
|
||||||
|
subtree = rootNode->Right;
|
||||||
|
subtree->Balance = rootNode->Balance;
|
||||||
|
subtree->Left = rootNode->Left;
|
||||||
|
free(rootNode->Name);
|
||||||
|
FreeElement(rootNode->Item);
|
||||||
|
free(rootNode);
|
||||||
|
rootNode = subtree;
|
||||||
|
} else {
|
||||||
|
/* rootNode is replaced by inorder successor */
|
||||||
|
/* re-using comp as another flag since it is 0 */
|
||||||
|
rootNode->Right = DeleteLeftMost(&rootNode, rootNode->Right, &comp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rootNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeNode *DeleteByElement(TreeNode *rootNode, Element Item)
|
||||||
|
{
|
||||||
|
short finished = 0;
|
||||||
|
TreeNode *newRoot = NULL;
|
||||||
|
newRoot = DeleteByElementRecursive(rootNode, Item, &finished);
|
||||||
|
return newRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
long Height(TreeNode *rootNode)
|
||||||
|
{
|
||||||
|
/* recursive function to determine the height by comparing the height of
|
||||||
|
the left and right child and returning the larger value */
|
||||||
|
long lresult = 0, rresult = 0;
|
||||||
|
/* either the tree is empty or we found a leaf */
|
||||||
|
if(rootNode == NULL)
|
||||||
|
return 0;
|
||||||
|
lresult = Height(rootNode->Left);
|
||||||
|
rresult = Height(rootNode->Right);
|
||||||
|
/* minimum height is 1, but that's probably correct */
|
||||||
|
return (lresult > rresult ? lresult : rresult) + 1;
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "Element.h"
|
||||||
|
|
||||||
|
short Compare(Element Data1, Element Data2)
|
||||||
|
{
|
||||||
|
if(*Data1 > *Data2)
|
||||||
|
return 1;
|
||||||
|
else if(*Data1 < *Data2)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreeElement(Element Data)
|
||||||
|
{
|
||||||
|
free(Data);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
#ifndef __Element_H
|
||||||
|
|
||||||
|
#define __Element_H
|
||||||
|
|
||||||
|
typedef long *Element;
|
||||||
|
|
||||||
|
short Compare(Element Data1, Element Data2);
|
||||||
|
|
||||||
|
void FreeElement(Element Data);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,55 @@
|
||||||
|
#ifndef __Tree_H
|
||||||
|
|
||||||
|
#define __Tree_H
|
||||||
|
|
||||||
|
#include "Element.h"
|
||||||
|
|
||||||
|
/* the basic tree structure
|
||||||
|
* the root of the complete tree is defined where Parent is NULL
|
||||||
|
*/
|
||||||
|
typedef struct TreeNodeTag {
|
||||||
|
struct TreeNodeTag *Left;
|
||||||
|
struct TreeNodeTag *Right;
|
||||||
|
Element Item;
|
||||||
|
char *Name;
|
||||||
|
short Balance;
|
||||||
|
} TreeNode;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function will find a particular TreeNode with the given
|
||||||
|
* Element as the Item.
|
||||||
|
*/
|
||||||
|
TreeNode *FindByElement(TreeNode *rootNode, const Element item);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function will return a boolean and determine if the given tree
|
||||||
|
* (or subtree) is empty.
|
||||||
|
*/
|
||||||
|
short IsEmpty(TreeNode *rootNode);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function will insert a given Element into the tree (subtree) and
|
||||||
|
* perform all neccessary adjustments to the tree. Returns the new root
|
||||||
|
* node.
|
||||||
|
*/
|
||||||
|
TreeNode *Insert(TreeNode *rootNode, Element Item, char *Name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function will remove all items from the give tree or subtree
|
||||||
|
*/
|
||||||
|
void MakeEmpty(TreeNode *rootNode);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Deletes a given TreeNode and will perform all neccessary adjustments
|
||||||
|
* to the tree. Returns the new root node. Note: the Name field will be
|
||||||
|
* free'd with the TreeNode.
|
||||||
|
*/
|
||||||
|
TreeNode *DeleteByElement(TreeNode *rootNode, Element Item);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determines the height of the given tree. Should be used with caution with
|
||||||
|
* large trees.
|
||||||
|
*/
|
||||||
|
long Height(TreeNode *rootNode);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,183 @@
|
||||||
|
/* A balanced binary search tree(AVLTree) implementation
|
||||||
|
* Written by Coleman
|
||||||
|
* Released under GNU GPL Version 2 or later(http://www.gnu.org/)
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include "Element.h"
|
||||||
|
#include "Tree.h"
|
||||||
|
|
||||||
|
#define MAXELEMENTSIZE 500000
|
||||||
|
|
||||||
|
int calcsize(TreeNode *tnode) {
|
||||||
|
long result = 0;
|
||||||
|
if(tnode == NULL)
|
||||||
|
return 0;
|
||||||
|
result = sizeof(tnode);
|
||||||
|
result +=(long)sizeof(Element);
|
||||||
|
result +=(long)sizeof(char) * strlen(tnode->Name);
|
||||||
|
result += calcsize(tnode->Left);
|
||||||
|
result += calcsize(tnode->Right);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void printTree(TreeNode *start, long level)
|
||||||
|
{
|
||||||
|
long i = 0;
|
||||||
|
if(start == NULL)
|
||||||
|
return;
|
||||||
|
printf("%s -> %ld, Balance %d\n", start->Name,
|
||||||
|
*start->Item, start->Balance);
|
||||||
|
for(i = 0; i < level; i++)
|
||||||
|
printf(" ");
|
||||||
|
printf("Left: ");
|
||||||
|
printTree(start->Left, level + 1);
|
||||||
|
printf("\n");
|
||||||
|
for(i = 0; i < level; i++)
|
||||||
|
printf(" ");
|
||||||
|
printf("Right: ");
|
||||||
|
printTree(start->Right, level + 1);
|
||||||
|
if(level == 0)
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
long breadth(TreeNode *start)
|
||||||
|
{
|
||||||
|
if(start == NULL)
|
||||||
|
return (long)0;
|
||||||
|
if(start->Left == NULL && start->Right == NULL)
|
||||||
|
return (long)1;
|
||||||
|
return (long)(breadth(start->Left) + breadth(start->Right));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
TreeNode *tree = NULL, *newTree = NULL;
|
||||||
|
Element newItem = NULL;
|
||||||
|
char *itemName = NULL;
|
||||||
|
long i = 0, topsize = 0, tick = 0, last = 0;
|
||||||
|
long height = 0, oldheight = 0;
|
||||||
|
|
||||||
|
/* get the command argument, used for a custom size parameter */
|
||||||
|
if(argc == 2)
|
||||||
|
topsize = atol(argv[1]);
|
||||||
|
if(topsize == 0 || topsize > MAXELEMENTSIZE)
|
||||||
|
topsize = 25;
|
||||||
|
tick = topsize / 20;
|
||||||
|
|
||||||
|
srand48((long)time(NULL));
|
||||||
|
printf("Start --> Finished\n");
|
||||||
|
for(i = 0; i < topsize; i++) {
|
||||||
|
newItem = malloc(sizeof(Element));
|
||||||
|
itemName = malloc(sizeof(char) * 11);
|
||||||
|
sprintf(itemName, "Name%ld", i);
|
||||||
|
do {
|
||||||
|
*newItem = lrand48();
|
||||||
|
newTree = Insert(tree, newItem, itemName);
|
||||||
|
if(newTree == NULL) {
|
||||||
|
if(last == *newItem) {
|
||||||
|
free(itemName);
|
||||||
|
free(newItem);
|
||||||
|
printf("going to try and skip: %ld\n", *newItem);
|
||||||
|
break;
|
||||||
|
} else
|
||||||
|
last = *newItem;
|
||||||
|
}
|
||||||
|
} while(newTree == NULL);
|
||||||
|
if(i % tick == 0) {
|
||||||
|
printf(".");
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
tree = newTree;
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
/* test out the delete functionality */
|
||||||
|
printf("\nGoing to delete the rootNode: %ld\n", *tree->Item);
|
||||||
|
newTree = DeleteByElement(tree, tree->Item);
|
||||||
|
if(newTree == NULL)
|
||||||
|
printf("failure!\n");
|
||||||
|
else {
|
||||||
|
tree = newTree;
|
||||||
|
printf("success! new root is %ld\n", *tree->Item);
|
||||||
|
}
|
||||||
|
printf("\nGoing to delete leftMost child... ");
|
||||||
|
for(newTree = tree;
|
||||||
|
newTree != NULL && newTree->Left != NULL;
|
||||||
|
newTree = newTree->Left) {}
|
||||||
|
if(newTree != NULL) {
|
||||||
|
printf("found item: %ld\n", *newTree->Item);
|
||||||
|
newTree = DeleteByElement(tree, newTree->Item);
|
||||||
|
if(newTree == NULL)
|
||||||
|
printf("failure!\n");
|
||||||
|
else {
|
||||||
|
printf("success! new root: %ld\n", *newTree->Item);
|
||||||
|
tree = newTree;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* duplicated from left side */
|
||||||
|
printf("\nGoing to delete rightMost child... ");
|
||||||
|
for(newTree = tree;
|
||||||
|
newTree != NULL && newTree->Right != NULL;
|
||||||
|
newTree = newTree->Right) {}
|
||||||
|
if(newTree != NULL) {
|
||||||
|
printf("found item: %ld\n", *newTree->Item);
|
||||||
|
newTree = DeleteByElement(tree, newTree->Item);
|
||||||
|
if(newTree == NULL)
|
||||||
|
printf("failure!\n");
|
||||||
|
else {
|
||||||
|
printf("success! new root: %ld\n", *newTree->Item);
|
||||||
|
tree = newTree;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
if(topsize <= 25)
|
||||||
|
printTree(tree, 0);
|
||||||
|
printf("sizeof(TreeNode) %d\n",(int)sizeof(TreeNode));
|
||||||
|
printf("sizeof(Element) %d\n",(int)sizeof(Element));
|
||||||
|
printf("sizeof(tree) %d\n", calcsize(tree));
|
||||||
|
printf("breadth of left tree: %ld right subtree: %ld\n",
|
||||||
|
breadth(tree->Left), breadth(tree->Right));
|
||||||
|
oldheight = Height(tree->Left);
|
||||||
|
printf("height of left subtree: %ld right subtree: %ld\n",
|
||||||
|
oldheight, Height(tree->Right));
|
||||||
|
|
||||||
|
last = (long)(LONG_MAX / 2);
|
||||||
|
for(i = 0; i < 3; i++) {
|
||||||
|
printf("\n");
|
||||||
|
height = lrand48() % oldheight;
|
||||||
|
printf("Going to delete a node at depth (max depth %ld): %ld\n",
|
||||||
|
oldheight, height);
|
||||||
|
newTree = tree;
|
||||||
|
do {
|
||||||
|
if(newTree->Left == NULL) {
|
||||||
|
if(newTree->Right == NULL)
|
||||||
|
break;
|
||||||
|
tick = last + 1;
|
||||||
|
} else if(newTree->Right == NULL)
|
||||||
|
tick = last - 1;
|
||||||
|
else
|
||||||
|
tick = lrand48();
|
||||||
|
newTree = (tick >= last ? newTree->Right : newTree->Left);
|
||||||
|
height--;
|
||||||
|
} while(height > 0);
|
||||||
|
printf("Found a node to delete with Name '%s' and Item %ld\n",
|
||||||
|
newTree->Name, *newTree->Item);
|
||||||
|
newTree = DeleteByElement(tree, newTree->Item);
|
||||||
|
if(newTree == NULL)
|
||||||
|
printf("failure!\n");
|
||||||
|
else {
|
||||||
|
printf("success! new root: %ld\n", *newTree->Item);
|
||||||
|
tree = newTree;
|
||||||
|
}
|
||||||
|
oldheight = (int)(oldheight * 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
MakeEmpty(tree);
|
||||||
|
return 0;
|
||||||
|
}
|
Reference in New Issue