알고리즘 - Bistree

Mokwon Univ 2008. 8. 16. 16:13
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "bistree.h"

static void destroy_right(BisTree *tree, BiTreeNode *node);

static int insert(BisTree *tree, BiTreeNode **node,const void *data,int *balanced);

BiTree *tree_ptr;
BiTreeNode *node_ptr;
int *bal_ptr;
void *key_ptr;

void main()
{
tree_ptr=(BiTree *)malloc(sizeof(BiTree));
bistree_init(tree_ptr,key_ptr,0);
insert(tree_ptr,node_ptr,3,bal_ptr);

printf("this: %d",tree_ptr->root);
}



//--------------------------rotate_left--------------------------------

static void rotate_left(BiTreeNode **node){
BiTreeNode *left, *grandchild;
left = bitree_left(*node);
if(((AvlNode *)bitree_data(left))->factor == AVL_LFT_HEAVY){

//perform an LL rotation

bitree_left(*node) = bitree_right(left);
bitree_right(left) = *node;
((AvlNode *)bitree_data(*node))->factor = AVL_BALANCED;
((AvlNode *)bitree_data(left))->factor = AVL_BALANCED;
*node = left;

}
else{

//perform an LR rotation

grandchild = bitree_right(left);
bitree_right(left) = bitree_left(grandchild);
bitree_left(grandchild) = left;
bitree_left(*node) = bitree_right(grandchild);
bitree_right(grandchild) = *node;

switch(((AvlNode * )bitree_data(grandchild))->factor) {

case AVL_LFT_HEAVY:

((AvlNode *)bitree_data(*node))->factor = AVL_RGT_HEAVY;
((AvlNode *)bitree_data(left))->factor = AVL_BALANCED;
break;

case AVL_BALANCED:

((AvlNode *)bitree_data(*node))->factor = AVL_BALANCED;
((AvlNode *)bitree_data(left))->factor = AVL_BALANCED;
break;

case AVL_RGT_HEAVY:

((AvlNode *)bitree_data(*node))->factor = AVL_BALANCED;
((AvlNode *)bitree_data(left))->factor = AVL_LFT_HEAVY;
break;
}

((AvlNode *)bitree_data(grandchild))->factor = AVL_BALANCED;
*node = grandchild;
}
return;
}





//--------------------------- rotate_right -------------------------------------


static void rotate_right(BiTreeNode **node){
BiTreeNode *right, *grandchild;
right = bitree_right(*node);
if(((AvlNode *)bitree_data(right))->factor == AVL_RGT_HEAVY){

//perform an RR rotation

bitree_right(*node) = bitree_left(right);
bitree_left(right) = *node;
((AvlNode *)bitree_data(* node))->factor = AVL_BALANCED;
((AvlNode *)bitree_data(right))->factor = AVL_BALANCED;
*node = right;

}
else{

//perform an RL rotation

grandchild = bitree_left(right);
bitree_left(right) = bitree_right(grandchild);
bitree_right(grandchild) = right;
bitree_right(*node) = bitree_left(grandchild);
bitree_left(grandchild) = *node;

switch(((AvlNode * )bitree_data(grandchild))->factor) {

case AVL_LFT_HEAVY:

((AvlNode *)bitree_data(*node))->factor = AVL_BALANCED;
((AvlNode *)bitree_data(right))->factor = AVL_RGT_HEAVY;
break;

case AVL_BALANCED:

((AvlNode *)bitree_data(*node))->factor = AVL_BALANCED;
((AvlNode *)bitree_data(right))->factor = AVL_BALANCED;
break;

case AVL_RGT_HEAVY:

((AvlNode *)bitree_data(*node))->factor = AVL_LFT_HEAVY;
((AvlNode *)bitree_data(right))->factor = AVL_BALANCED;
break;
}

((AvlNode *)bitree_data(grandchild))->factor = AVL_BALANCED;
*node = grandchild;
}
return;
}




//------------------------destroy_left------------------------------

static void destroy_left(BisTree *tree, BiTreeNode *node){
BiTreeNode **position;

//do not allow destructoin of an empty tree
if(bitree_size(tree)==0)
return;

//determine where to destroy nodes
if(node==NULL)
position = &tree->root;
else
position = &node->left;

//destroy the nodes
if(*position != NULL){

destroy_left(tree, *position);
destroy_right(tree, *position);

if(tree->destroy !=NULL){

//call a user-defined function to tree dynamically allocated data

tree->destroy(((AvlNode *)(*position)->data)->data);
}

//Free the AVL data in the node, then free the node itself

free((*position)->data);
free(*position);
*position = NULL;

//adjust the size of the tree to account for the destroyed node

tree->size--;
}
return;
}






//------------------------destroy_right------------------------------

static void destroy_right(BisTree *tree, BiTreeNode *node){
BiTreeNode **position;

//do not allow destructoin of an empty tree
if(bitree_size(tree)==0)
return;

//determine where to destroy nodes
if(node==NULL)
position = &tree->root;
else
position = &node->right;

//destroy the nodes
if(*position != NULL){

destroy_left(tree, *position);
destroy_right(tree, *position);

if(tree->destroy !=NULL){

//call a user-defined function to tree dynamically allocated data

tree->destroy(((AvlNode *)(*position)->data)->data);
}

//Free the AVL data in the node, then free the node itself

free((*position)->data);
free(*position);
*position = NULL;

//adjust the size of the tree to account for the destroyed node

tree->size--;
}
return;
}



//------------------------insert---------------------

static int insert(BisTree *tree, BiTreeNode **node, const void *data, int *balanced){
AvlNode *avl_data;
int cmpval, retval;

//insert the data into the tree

if(bitree_is_eob(*node)){

//Handle insertion into an empty tree

if((avl_data = (AvlNode *)malloc(sizeof(AvlNode))) == NULL)
return -1;
avl_data->factor = AVL_BALANCED;
avl_data->hidden = 0;
avl_data->data = (void *)data;

return bitree_ins_left(tree, *node, avl_data);
}

else{

//Handle insertion into a tree that is not empty

cmpval = tree->compare(data, ((AvlNode *)bitree_data(*node))->data);
if(cmpval <0){

//Move to the left

if(bitree_is_eob(bitree_left(*node))){
if((avl_data = (AvlNode *)malloc(sizeof(AvlNode))) == NULL)
return -1;

avl_data->factor = AVL_BALANCED;
avl_data->hidden = 0;
avl_data->data = (void *)data;

if (bitree_ins_left(tree, *node, avl_data) != 0)
return -1;

*balanced = 0;
}

else{

if((retval = insert(tree, &bitree_left(*node), data, balanced))!=0){
return retval;
}
}

//ensure that the tree remains balanced

if(!(*balanced)){
switch (((AvlNode *)bitree_data(*node))->factor){

case AVL_LFT_HEAVY:

rotate_left(node);
*balanced = 1;
break;

case AVL_BALANCED:

((AvlNode *)bitree_data(* node))->factor = AVL_LFT_HEAVY;
break;

case AVL_RGT_HEAVY:

((AvlNode *)bitree_data(*node))->factor = AVL_BALANCED;
*balanced = 1;

}
}
}

else if (cmpval > 0) {

//move to the right

if(bitree_is_eob(bitree_right(*node))){
if((avl_data = (AvlNode *)malloc(sizeof(AvlNode))) == NULL)
return -1;

avl_data->factor = AVL_BALANCED;
avl_data->hidden = 0;
avl_data->data = (void *)data;

if (bitree_ins_right(tree, *node, avl_data) != 0)
return -1;

*balanced = 0;
}

else{

if((retval = insert(tree, &bitree_right(*node), data, balanced))!=0){
return retval;
}
}

//ensure that the tree remains balanced

if(!(*balanced)){
switch (((AvlNode *)bitree_data(*node))->factor){

case AVL_LFT_HEAVY:

((AvlNode *)bitree_data(* node))->factor = AVL_BALANCED;
*balanced = 1;
break;

case AVL_BALANCED:

((AvlNode *)bitree_data(* node))->factor = AVL_RGT_HEAVY;
break;

case AVL_RGT_HEAVY:

rotate_right(node);
*balanced = 1;

}
}
} //if (cmpval >0)

else {

//Handle finding a copy of the data

if(!((AvlNode *)bitree_data(*node))->hidden){

//Do nothing since the data is in the tree and not hidden

return 1;

}

else{

//Insert the new data and mark it is being replaced

if(tree->destroy != NULL){

//destroy the hidden data since it is being replaced

tree->destroy(((AvlNode *)bitree_data(*node))->data);
}

((AvlNode *)bitree_data(*node))->data = (void *)data;
((AvlNode *)bitree_data(*node))->hidden = 0;

//Do not rebalanced because the tree structure is unchange

*balanced = 1;
}
}
}
return 0;

}






// --------------------------- hide -------------------

static int hide(BisTree *tree, BiTreeNode *node, const void *data){
int cmpval, retval;

if(bitree_is_eob(node)){

//Return that the data was not found

return -1;
}

cmpval = tree->compare(data, ((AvlNode *)bitree_data(node))->data);

if (cmpval < 0){

// move to the left

retval = hide(tree, bitree_left(node), data);
}

else if (cmpval >0){

//move to the right

retval = hide(tree, bitree_right(node), data);
}
else{

// Mark the node as hidden

((AvlNode *)bitree_data(node))->hidden =1;
retval = 0;
}

return retval;

}






// ------------------------ look up ---------------------


static int lookup(BisTree *tree, BiTreeNode *node, void **data){
int cmpval,retval;

if(bitree_is_eob(node)){

// Return that the data was not found

return -1;
}

cmpval = tree->compare(*data, ((AvlNode *)bitree_data(node))->data);

if(cmpval < 0){

//Move to the left

retval = lookup(tree,bitree_left(node),data);
}

else if (cmpval >0){

//Move to the right

retval = lookup(tree,bitree_right(node),data);
}

else{
if(!((AvlNode *)bitree_data(node))->hidden){

// Pass back the data from the tree

*data = ((AvlNode *)bitree_data(node))->data;
retval = 0;
}
else{

//Return that the data was not found

return -1;
}
}
return retval;
}





// ---------------------- bistree_init ------------------

void bistree_init(BisTree *tree, int (*compare)(const void *key1,
const void *key2),void(*destroy)(void *data)){

// Initialize the tree

bitree_init(tree, destroy);
tree->compare = compare;

return;
}





// ------------------------bistree_sedtory-------------------------

void bistree_destroy(BisTree *tree){

//destroy all nodes in the tree

destroy_left(tree, NULL);

// no operation are allowed now, but clear the structure as a precaution

memset(tree, 0, sizeof(BisTree));

return;
}




//------------------------ bistree_insert-----------------------

int bistree_insert(BisTree *tree, const void *data) {
int balanced = 0;

return insert(tree, &bitree_root(tree), data, &balanced);
}


//-------------------------bistree_remove--------------------------

int bistree_remove(BisTree *tree, const void *data){
return hide(tree, bitree_root(tree), data);
}



//-------------------------bistree_lookup-------------------------

int bistree_lookup(BisTree *tree, void **data){
return lookup(tree, bitree_root(tree), data);
}
 
출처 - c로 구현한 알고리즘 한빛미디어
Posted by 용학도리
,