二叉樹搜索樹概念
二叉搜索樹是由二叉樹組成的專用於查找和搜索的一種數據結構。需要在二叉樹中查詢一個節點,從根節點開始一層層往下查找,直到找到目標節點爲止。當遇到一個比目標節點值大的節點時,順着該節點的左子樹繼續查找。如果遇到的節點值小於目標節點,則順着該節點的右子樹繼續查找。(左分支的數,一定小於右分支的數,個人覺得類似二分查找)
二叉搜索樹是一種用於查找操作的高效數據結構,最壞情況只需查找一個分支 的數據即可,而不用檢索所有數據,所以操作的複雜度爲O(lg n).
代碼實現
#include"bitree.h"
typedef BiTree BisTree;
//初始化二叉搜索樹,compare用於比較key1>key2?1:-1(= 0)
void bistree_init(BisTree *tree, void(*compare)(const void *key1, const void *key2),
void(*destroy)(void *data));
//銷燬樹
void bistree_destroy(BisTree *tree);
//插入節點,成功返回0,要插入的節點已存在返回1,否則-1
int bistree_insert(BisTree *tree, const void *data); //複雜度lg n
//移除等於data的節點,成功返回0,否則-1
int bistree_remove(BisTree *tree, const void *data); //複雜度lg n
//查找對應data的節點,成功返回0,否則-1
int bistree_lookup(const BisTree *tree, void **data); //複雜度lg n
//銷燬node節點開始的左分支
static void destroy_right(BisTree *tree, BiTreeNode *node);
static void destroy_left(BisTree *tree, BiTreeNode *node)
{
BiTreeNode **position;
if (tree->size == 0) return; //如果樹節點爲0 ,直接返回
if (node == NULL) //如果node爲null,從根節點開始刪除
position = &tree->root;
else
position = &node->left;
if (*position != NULL)
{
//遞歸消除position開始的左右子樹
destroy_left(tree, *position);
destroy_right(tree, *position);
if (tree->destroy != NULL)
{
//調用析構函數;
}
//釋放節點空間,size--
free((*position)->data);
free(*position);
*position = NULL;
tree->size--;
}
return;
}
//在樹tree的node節點開始插入data數據
static int insert(BisTree *tree, BiTreeNode **node, const void *data)
{
int cmpval, retval;
if (bitree_is_eob(*node)) //如果指定節點沒有左右節點,從左節點開始插入
{
return bitree_ins_left(tree, *node, data);
}
else
{
cmpval = tree->compare(data, (*node)->data); //比較node->data和data的值,data大時,右子樹插入
if (cmpval < 0)
{
if (bitree_is_eob((*node)->left)) //如果node->left爲空
{
if (bitree_ins_left(tree, *node, data) != 0)
return -1;
}
else
{
if ((retval = insert(tree, &((*node)->left), data)) != 0)
{
return retval;
}
}
}
else if(cmpval > 0)
{
if (bitree_is_eob((*node)->right)) //如果node->left爲空
{
if (bitree_ins_right(tree, *node, data) != 0)
return -1;
}
else
{
if ((retval = insert(tree, &((*node)->right), data)) != 0)
{
return retval;
}
}
}
else //如果node->data == data,則爲數據衝突
{
if (tree->destroy != NULL)
tree->destroy((*node)->data);
(*node)->data = data; //此處,不能講const data賦值給*node->data
}
}
return 0;
}
//在樹tree的node節點開始查找data數據
static int lookup(BisTree *tree, BiTreeNode *node,const void **data)
{
int cmpval, retval;
if (bitree_is_eob(node)) //node的左右節點不爲空
{
return -1;
}
//比較插入節點和要插入數據的值
cmpval = tree->compare(*data, node->data);
if (cmpval < 0) //如果插入數據小於node->data,在node的左子樹尋找位置繼續比較
retval = lookup(tree, node->left, data);
else if (cmpval > 0) //如果插入數據大於node->data,在node的右子樹尋找位置繼續比較
retval = lookup(tree, node->right, data);
else //等於時,取出數據
{
*data = node->data;
}
return retval;
}
void bistree_init(BisTree *tree, int(*compare)(const void *key1, const void *key2), void(*destroy)(void *data))
{
bitree_init(tree, destroy);
tree->compare = compare;
return;
}
void bistree_destroy(BisTree *tree)
{
destroy_left(tree, NULL);
memset(tree, 0, sizeof(BisTree));
return;
}
int bistree_insert(BisTree *tree, const void *data)
{
return insert(tree, &(tree->root), data);
}
int bistree_remove(BisTree *tree, const void *data)
{
return lookup(tree, tree->root, &data);
}
int bistree_lookup(BisTree *tree, void **data)
{
return lookup(tree, tree->root, data);
}