定义
二叉排序树(Binary Sort Tree)又称二叉查找树(Binary Search Tree),也称为二叉搜索树。二叉排序树或者是一棵空树,或者是具有下列特点的二叉树:
1. 若左子树不空,其左子树上所有结点的值均小于它的根结点的值;
2. 若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
3. 结点的左、右子树也分别是一个二叉排序树.
如下为一个典型的二叉搜索树:
二叉排序树的基本操作
1 二叉树的构建
目前含有如下元素 23, 19, 29, 16, 21, 32, 20,其构建流程为:
1 首先插入元素23;
2 元素19小于元素23,根据规则将19插入23的左子树中;
3 元素29大于元素23,根据规则将29插入23的右子树中;
4 元素16小于元素19,根据规则将16插入19的左子树中;
5 元素21大于元素19小于元素23,根据规则将21插入19的右子树中;
6 元素32大于元素29,根据规则将32插入29的右子树中;
7 元素20大于元素19小于元素21,根据规则将20插入21的左子树中;
2 二叉搜索树的查找操作
例:从上述二叉搜索树查找元素 21,流程如下:23 --> 19 --> 21
1 首先与根节点进行比较,21 小于 23,可知应在其左子树中进行查找;
2 元素19小于元素21,根据规则应在元素19的右子树中进行查找;
3 元素21大于元素21,成功查找到,结束。
3 二叉搜索树的插入操作
向上述二叉搜索树中插入元素 22,流程如下【首先找到插入位点,插入位点为叶子结点的指针域中,后修改父节点的指针域】:
1 根据查找规则找到插入位点,即插入位点为元素 21的右子树中;
2 将元素21 的右指针域指向元素 22。
4 二叉搜索树的删除操作
4.1 删除元素为叶子结点,无左右子树(看图更明了)
4.2 删除元素非叶子结点,但含有子左右子树中的一个(看图更明了)
4.3 删除元素为非叶子结点,同时含有左右子树,该情况稍复杂
1 根据查找规则找到删除元素;
2 确定右子树,找到右子树中的最小值元素 xmin。
3 将待删除元素与xmin互换位置,更新对应的指针域信息
源代码实现
binary_sort_tree.h
#ifndef BINARY_SORT_TREE_H
#define BINARY_SORT_TREE_H
typedef int Elemtype;
typedef enum
{
TRUE,
FALSE,
NON_ALLOCATED
} Status;
typedef struct BSNode{
Elemtype item;
struct BSNode *lchild;
struct BSNode *rchild;
} BSNode;
typedef struct BStree{
BSNode *root;
int size;
} BSTree;
void InitBSTree(BSTree *ptree);
Status BSTreeIsFull(const BSTree *ptree);
Status BSTreeIsEmpty(const BSTree *ptree);
Status BSTreeSearch(const BSTree *ptree, Elemtype key);
Status BSTreeInsert(BSTree *ptree, Elemtype key);
Status BSTreeDelete(BSTree *ptree, Elemtype key);
int BSTreeDepth(const BSTree *ptree);
void InorderShowBSTree(const BSTree *ptree);
void PostShowBSTree(const BSTree *ptree);
void DeleteAll(BSTree *ptree);
#endif //BINARY_SORT_TREE_H
#include <stdio.h>
#include <stdlib.h>
typedef struct pair
{
BSNode *parent;
BSNode *child;
} pair;
static BSNode *MakeNode(const Elemtype key);
static void AddNode(BSNode *newnode, BSNode *root);
static void DeleteNode(BSNode **delnode);
static pair Seek(const BSTree *ptree, Elemtype key);
static void traverse(BSNode *root);
static void DeleteAllNode(BSNode *root);
void InitBSTree(BSTree *ptree)
{
ptree->root = NULL;
ptree->size = 0;
}
Status BSTreeIsFull(const BSTree *ptree)
{
BSNode *tmp = (BSNode *)malloc(sizeof(BSNode));
if (tmp == NULL)
return TRUE;
else
return FALSE;
}
Status BSTreeIsEmpty(const BSTree *ptree)
{
if (ptree->size == 0)
return TRUE;
else
return FALSE;
}
Status BSTreeSearch(const BSTree *ptree, Elemtype key)
{
return (Seek(ptree, key).child == NULL ? FALSE : TRUE);
}
Status BSTreeInsert(BSTree *ptree, Elemtype key)
{
BSNode *newnode;
if (Seek(ptree, key).child != NULL)
{
printf("erroe, do not insert same elemnt of BSTree\n");
return FALSE;
}
newnode = MakeNode(key);
if (newnode == NULL)
{
printf("error, can not create a BSNode since out of memory!\n");
return FALSE;
}
if(ptree->root == NULL)
ptree->root = newnode;
else
AddNode(newnode, ptree->root);
ptree->size++;
return TRUE;
}
Status BSTreeDelete(BSTree *ptree, Elemtype key)
{
pair look;
if (!BSTreeIsEmpty(ptree))
{
printf("BSTree is empty!!!\n");
return FALSE;
}
look = Seek(ptree, key);
if (look.child == NULL)
{
printf("delete element is not exist!\n");
return FALSE;
}
else if (look.parent == NULL)
{
DeleteNode(&look.parent);
}
else if (look.parent->lchild == look.child)
DeleteNode(&look.parent->lchild);
else if (look.parent->rchild == look.child)
DeleteNode(&look.parent->rchild);
ptree->size--;
return TRUE;
}
void InorderShowBSTree(const BSTree *ptree)
{
if (ptree != NULL)
traverse(ptree->root);
printf("\n");
}
static BSNode *MakeNode(const Elemtype key)
{
BSNode *new_node = (BSNode *)malloc(sizeof(BSNode));
if (new_node != NULL)
{
new_node->item = key;
new_node->lchild = NULL;
new_node->rchild = NULL;
}
return new_node;
}
static void traverse(BSNode *root)
{
if (root == NULL)
return;
traverse(root->lchild);
printf("%d\t", root->item);
traverse(root->rchild);
}
void FreeBSTree(BSTree *ptree)
{
if (ptree != NULL)
DeleteAllNode(ptree->root);
ptree->size = 0;
ptree->root = NULL;
}
static pair Seek(const BSTree *ptree, Elemtype key)
{
pair look;
look.parent = NULL;
look.child = ptree->root;
if (look.child == NULL)
return look;
while (look.child != NULL)
{
if (key < look.child->item)
{
look.parent = look.child;
look.child = look.child->lchild;
}
else if (key > look.child->item)
{
look.parent = look.child;
look.child = look.child->rchild;
}
else
{
break;
}
}
return look;
}
static void AddNode(BSNode *newnode, BSNode *root)
{
if (root->item > newnode->item)
{
if (root->lchild == NULL)
root->lchild = newnode;
else
{
AddNode(newnode, root->lchild);
}
}
else if (root->item < newnode->item)
{
if (root->rchild == NULL)
root->rchild = newnode;
else
AddNode(newnode, root->rchild);
}
else
{
printf("location error !!!\n");
exit(1);
}
}
int Max_Depth(BSNode *root)
{
if(root == NULL)
return 0;
int leftdepth = Max_Depth(root->lchild);
int rightdepth = Max_Depth(root->rchild);
return (leftdepth > rightdepth) ? leftdepth + 1 : rightdepth + 1;
}
int BSTreeDepth(const BSTree *ptree)
{
if(ptree != NULL)
{
return Max_Depth(ptree->root);
}
}
static void DeleteNode(BSNode **delnode)
{
BSNode *temp;
if ((*delnode)->lchild == NULL)
{
temp = *delnode;
(*delnode) = (*delnode)->rchild;
free(temp);
}
else if ((*delnode)->rchild == NULL)
{
temp = *delnode;
(*delnode) = (*delnode)->lchild;
free(temp);
}
else
{
for (temp = (*delnode)->lchild; temp->rchild; temp = temp->rchild)
break;
temp->rchild = (*delnode)->rchild;
temp = *delnode;
(*delnode) = (*delnode)->lchild;
free(temp);
}
}
static void DeleteAllNode(BSNode *root)
{
if (root == NULL)
return;
BSNode *pright;
{
pright = root->rchild; // 指向右子树
DeleteAllNode(root->lchild); // 递归删除最左子树节点
free(root); // 删除中节点
DeleteAllNode(pright); // 删除右节点
}
}
void DeleteAll(BSTree *ptree)
{
if(ptree != NULL)
DeleteAllNode(ptree->root);
ptree->root = NULL;
ptree->size = 0;
}
int main()
{
BSTree root;
InitBSTree(&root);
BSTreeInsert(&root, 23);
BSTreeInsert(&root, 34);
BSTreeInsert(&root, 13);
InorderShowBSTree(&root);
printf("The max_depth is %d\n", BSTreeDepth(&root));
BSTreeDelete(&root, 34);
Status result = BSTreeSearch(&root, 43);
if (result == TRUE)
{
printf("Found it\n");
}
else
printf("Not Found\n");
InorderShowBSTree(&root);
DeleteAll(&root);
return 0;
}
测试结果如下所示: