1、树的定义:树是算法中常用的数据结构。以下给出针对于二叉树、以及二叉搜索树的代码实现。
2、代码实现
(1)二叉树
<span style="font-size:18px;"><span style="font-size:14px;">/*bitree.h*/
#ifndef BITREE_H
#define BITREE_H
#include<stdlib.h>
/*define a structure for binary tree nodes*/
typedef struct BiTreeNode_
{
void *data;
struct BiTreeNode_ *left;
struct BiTreeNode_ *right;
}BiTreeNode;
/*define a stucture for binary tree*/
typedef struct BiTree_
{
int size;
int (*compare)(const void *key1,const void *key2);
void (*destroy)(void *data);
BiTreeNode *root;
}BiTree;
/*public interface*/
void bitree_init(BiTree *tree,void (*destroy)(void *data));
void bitree_destroy(BiTree *tree);
int bitree_ins_left(BiTree *tree,BiTreeNode *node,const void *data);
int bitree_ins_right(BiTree *tree,BiTreeNode *node,const void *data);
void bitree_rem_left(BiTree *tree,BiTreeNode *node);
void bitree_rem_right(BiTree *tree,BiTreeNode *node);
int bitree_merge(BiTree *merge,BiTree *left,BiTree *right,const void *data);
#define bitree_size(tree) ((tree)->size)
#define bitree_root(tree) ((tree)->root)
#define bitree_is_eob(tree) ((node)==NULL)
#define bitree_is_leaf(tree) ((node)->left==NULL && (node)->right==NULL)
#define bitree_data(node) ((node)->data)
#define bitree_left(node) ((node)->left)
#define bitree_right(node) ((node)->right)
#endif
</span></span>
<span style="font-size:18px;"><span style="font-size:14px;">/*bitree.c*/
#include<stdlib.h>
#include<string.h>
#include"bitree.h"
void bitree_init(BiTree *tree,void (*destroy)(void *data))
{
/*initialize the binary tree*/
tree->size=0;
tree->destroy=destroy;
tree->root=NULL;
return ;
}
void bitree_destroy(BiTree *tree)
{
/*remove all the nodes from the tree*/
bitree_rem_left(tree,NULL);
/*clear the structure*/
memset(tree,0,sizeof(BiTree));
return;
}
int bitree_ins_left(BiTree *tree,BiTreeNode *node,const void *data)
{
BiTreeNode *new_node,**position;
/*determine where to insert the node*/
if(node==NULL)
{
/*allow insertion at the root only in an empty tree*/
if(bitree_size(tree)>0)
return -1;
position=&tree->root;
}
else
{
/*normally allow insertion only at the end of a branch*/
if(bitree_left(node)!=NULL)
return -1;
position=&node->left;
}
/*allocate storage for the node*/
if((new_node=(BiTreeNode *)malloc(sizeof(BiTreeNode)))==NULL)
return -1;
/*insert the node into the tree*/
new_node->data=(void *)data;
new_node->left=NULL;
new_node->right=NULL;
*position=new_node;
/*adjust the size of the tree to account for the inserted node*/
tree->size++;
return 0;
}
int bitree_ins_right(BiTree *tree,BiTreeNode *node,const void *data)
{
BiTreeNode *new_node,**position;
/*determine where to insert the node*/
if(node==NULL)
{
/*allow insertion at the root only in an empty tree*/
if(bitree_size(tree)>0)
return -1;
position=&tree->root;
}
else
{
/*normally allow insertion only at the end of a branch*/
if(bitree_left(node)!=NULL)
return -1;
position=&node->right;
}
/*allocate storage for the node*/
if((new_node=(BiTreeNode *)malloc(sizeof(BiTreeNode)))==NULL)
return -1;
/*insert the node into the tree*/
new_node->data=(void *)data;
new_node->left=NULL;
new_node->right=NULL;
*position=new_node;
/*adjust the size of the tree to account for the inserted node*/
tree->size++;
return 0;
}
void bitree_rem_left(BiTree *tree,BiTreeNode *node)
{
BiTreeNode **position;
/*do not allow removal from an empty tree*/
if(bitree_size(tree)==0)
return;
/*determine where to remove node*/
if(node==NULL)
position=&tree->root;
else
position=&node->left;
/*remove the nodes*/
if(*position!=NULL)
{
bitree_rem_left(tree,*position);
bitree_rem_right(tree,*position);
if(tree->destroy!=NULL)
{
/*call a user-defined function to free dynamically allocated data*/
tree->destroy((*position)->data);
}
free(*position);
*position=NULL;
/*adjust the size of the tree to account for the removed node*/
tree->size--;
}
return ;
}
void bitree_rem_right(BiTree *tree,BiTreeNode *node)
{
BiTreeNode **position;
/*do not allow removal from an empty tree*/
if(bitree_size(tree)==0)
return;
/*determine where to remove node*/
if(node==NULL)
position=&tree->root;
else
position=&node->right;
/*remove the nodes*/
if(*position!=NULL)
{
bitree_rem_left(tree,*position);
bitree_rem_right(tree,*position);
if(tree->destroy!=NULL)
{
/*call a user-defined function to free dynamically allocated data*/
tree->destroy((*position)->data);
}
free(*position);
*position=NULL;
/*adjust the size of the tree to account for the removed node*/
tree->size--;
}
return ;
}
int bitree_merge(BiTree *merge,BiTree *left,BiTree *right,const void *data)
{
/*initialize the merged tree*/
bitree_init(merge,left->destroy);
/*insert the data for the root node of the merged tree*/
if(bitree_ins_left(merge,NULL,data)!=0)
{
bitree_destroy(merge);
return -1;
}
/*merge the two binary trees into a single binary tree*/
bitree_root(merge)->left=bitree_root(left);
bitree_root(merge)->right=bitree_root(right);
/*adjust the size of the new binary tree*/
merge->size=merge->size+bitree_size(left)+bitree_size(right);
/*do not let original trees access the merged nodes*/
left->root=NULL;
left->size=0;
right->root=NULL;
right->size=0;
return 0;
}
</span></span>
应用实例:
后续补上
(2)二叉搜索树
<span style="font-size:18px;"><span style="font-size:14px;">/*bistree.h 二叉搜索树*/
#ifndef BISTREE_H
#define BISTREE_H
#include "bitree.h"
/*define balance factors for AVL trees*/
#define AVL_LFT_HEAVY 1
#define AVL_BALANCED 0
#define AVL_RGT_HEAVY -1
/*define a structure for node in AVL trees*/
typedef struct AvlNode_
{
void *data;
int hidden;
int factor;
}AvlNode;
/*implement binary search trees as binary trees*/
typedef BiTree BisTree;
/*public interface*/
void bistree_init(BisTree *tree,int (*compare)(const void *key1,const void *key2),void (*destroy)(void *data));
void bistree_destroy(BisTree *tree);
int bistree_insert(BisTree *tree,const void *data);
int bistree_remove(BisTree *tree,const void *data);
int bistree_lookup(BisTree *tree,void **data);
#define bistree_size(tree) ((tree)->size)
#endif</span></span>
<span style="font-size:18px;"><span style="font-size:14px;">/*bistree.c二叉搜索树*/
#include<stdlib.h>
#include<string.h>
#include"bistree.h"
static void destroy_right(BisTree *tree,BiTreeNode *node);
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_left(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;
}
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_right(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;
}
static void destroy_left(BisTree *tree,BiTreeNode *node)
{
BiTreeNode **position;
/*do not allow destruction 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-define function to free 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;
/*Ajust the size*/
tree->size--;
}
return ;
}
static void destroy_right(BisTree *tree,BiTreeNode *node)
{
BiTreeNode **position;
/*do not allow destruction 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-define function to free 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;
/*Ajust the size*/
tree->size--;
}
return ;
}
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;
break;
}
}
}
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;
break;
}
}
}
else
{
/*handle finding a copy for 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 mask it as no hidden*/
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 rebalance because the tree structure is unchanged*/
*balanced=1;
}
}
}
return 0;
}
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;
}
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 riht*/
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 no found*/
return -1;
}
}
return retval;
}
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;
}
void bistree_destroy(BisTree *tree)
{
/*destroy all node in the tree*/
destroy_left(tree,NULL);
memset(tree,0,sizeof(BisTree));
return;
}
int bistree_insert(BisTree *tree,const void *data)
{
int balanced=0;
return insert(tree,&bitree_root(tree),data,&balanced);
}
int bistree_remove(BisTree *tree,const void *data)
{
return hide(tree,bitree_root(tree),data);
}
int bistree_lookup(BisTree *tree,void **data)
{
return lookup(tree,bitree_root(tree),data);
}</span></span>
应用实例:
后续补上