一、介绍
二叉搜索树(Binary Search Tree),或者是一棵空树,或者是具有下列性质的二叉树:
1,若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;2,若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
3,它的左、右子树也分别为二叉搜索树。
二叉搜索树的查找过程和次优二叉树类似,通常采取二叉链表作为二叉搜索序树的存储结构。中序遍历二叉搜索树可得到一个关键字的有序序列,
一个无序序列可以通过构造一棵二叉搜索树变成一个有序序列,构造树的过程即为对无序序列进行排序的过程。每次插入的新的结点都是二叉搜索
树上新的叶子结点,在进行插入操作时,不必移动其它结点,只需改动某个结点的指针,由空变为非空即可。搜索,插入,删除的复杂度等于树高,
O(log(n)) .
基本结构为:
typedef int type;
typedef struct node
{
type value;
struct node *left;
struct node *right;
}Search_tree;
二、基本操作
创建和删除二叉搜素树:
Search_tree *search_tree_create(type value)//创建
{
Search_tree *p = (Search_tree*)malloc(sizeof(Search_tree));
if(NULL == p)
return NULL;
p->value = value;
p->left = p->right = NULL;
return p;
}
void search_tree_destroy(Search_tree *t)//删除(释放)
{
if(t)
{
if(t->left)
search_tree_destroy(t->left);
if(t->right)
search_tree_destroy(t->right);
free(t);
t = NULL;
}
}
查找
在二叉搜索树t中查找value的过程为:
1,若t是空树,则搜索失败,否则:
2,若value等于t的根结点的数据域之值,则查找成功;否则:
3,若value小于t的根结点的数据域之值,则搜索左子树;否则:
4,查找右子树。
Search_tree *search_tree_find(Search_tree *t, type value)//根据指定值查找
{
if(t == NULL)
return NULL;
if(t->value == value)
return t;
else if(t->value > value)
return search_tree_find(t->left, value);
else
return search_tree_find(t->right, value);
}
插入
向一个二叉搜索树t中插入一个结点s的算法,过程为:
1,若t是空树,则将创建结点作为根结点插入,否则:
2,若value小于t 的根结点的数据域之值,则把value插入到左子树中,否则:
3,把value插入到右子树中。否则(包括已存在value值的节点) 返回。
Search_tree *search_tree_insert(Search_tree *t, type value)
{
if(t == NULL)// no root
t = search_tree_create(value);
else if(t->value > value)
t->left = search_tree_insert(t->left, value);
else if(t->value < value)
t->right = search_tree_insert(t->right, value);
return t;
}
删除(二叉搜索树的重点,难点)
在二叉搜索树删去一个结点,分三种情况讨论:
1,若*p结点为叶子结点,即PL(左子树)和PR(右子树)均为空树。由于删去叶子结点不破坏整棵树的结构,则只需修改其双亲结点的指针为空即可。
2,若*p结点只有左子树PL或右子树PR,此时只要令PL或PR直接成为其双亲结点*f的左子树(或者右子树)即可,作此修改也不破坏二叉搜索树的特性。
3,若*p结点的左子树和右子树均不空。在删去*p之后,为保持其它元素之间的相对位置不变,可按中序遍历保持有序进行调整,我们的做法是搜索节点p右子树上值最小的节点min并用min的值代替p的值,最后利用方法2把节点p的右子树的min节点删除即可(可以画图看下,和实际情况符合)。
在二叉搜索树上删除一个结点的算法如下:
bool search_tree_delete(Search_tree *t, type value)//删除节点
{
if(t == NULL)
return false;
Search_tree *p=t,*prev;//
while(p && p->value!=value)
{
prev=p;
if(p->value>value)
p=p->left;
else
p=p->right;
}
if(p == NULL)
return false;
if(p->left && p->right)// left right are all exist
{
Search_tree *min=p->right;//右子树最小节点
prev=p;
while(min->left)//找到右子树最小节点
{
prev=min;
min=min->left;
}
p->value=min->value;//把找到的右子树的最值与p进行值交换
/*将min节点的子节点作为prev的子节点,并将min所指向的节点删除*/
if(prev->right==min)
prev->right=min->right;//
else
prev->left=min->right;
}
else
{
if(prev->left==p)//p为左
{
prev->left=p->left ? p->left:p->right;
}
else if(prev->right==p)//p为右
{
prev->right=p->left ? p->left:p->right;
}
free(p);
p=NULL;
}
return true;
}
完整代码如下:
#include <stdio.h>
#include <stdlib.h>
typedef int type;
typedef struct node
{
type value;
struct node *left;
struct node *right;
}Search_tree;
Search_tree *search_tree_create(type value)//创建
{
Search_tree *p = (Search_tree*)malloc(sizeof(Search_tree));
if(NULL == p)
return NULL;
p->value = value;
p->left = p->right = NULL;
return p;
}
void search_tree_destroy(Search_tree *t)//销毁
{
if(t)
{
if(t->left)
search_tree_destroy(t->left);
if(t->right)
search_tree_destroy(t->right);
free(t);
t = NULL;
}
}
Search_tree *search_tree_find(Search_tree *t, type value)//根据指定值查找
{
if(t == NULL)
return NULL;
if(t->value == value)
return t;
else if(t->value > value)
return search_tree_find(t->left, value);
else
return search_tree_find(t->right, value);
}
Search_tree *search_tree_min(Search_tree *t)//搜索最小节点
{
if(NULL == t)
return NULL;
Search_tree *p = t;
while(p->left)
p = p->left;
return p;
}
Search_tree *search_tree_max(Search_tree *t)//搜索最大节点
{
if(NULL == t)
return NULL;
Search_tree *p = t;
while(p->right)
p = p->right;
return p;
}
Search_tree *search_tree_insert(Search_tree *t, type value)//插入
{
if(t == NULL)// no root
t = search_tree_create(value);
else if(t->value > value)
t->left = search_tree_insert(t->left, value);
else if(t->value < value)
t->right = search_tree_insert(t->right, value);
return t;
}
bool search_tree_delete(Search_tree *t, type value)//删除节点
{
if(t == NULL)
return false;
Search_tree *p=t,*prev;//
while(p && p->value!=value)
{
prev=p;
if(p->value>value)
p=p->left;
else
p=p->right;
}
if(p == NULL)
return false;
if(p->left && p->right)// left right are all exist
{
Search_tree *min=p->right;//右子树最小节点
prev=p;
while(min->left)//找到右子树最小节点
{
prev=min;
min=min->left;
}
p->value=min->value;//把找到的右子树的最值与p进行值交换
/*将min节点的子节点作为prev的子节点,并将min所指向的节点删除*/
if(prev->right==min)
prev->right=min->right;//
else
prev->left=min->right;
}
else
{
if(prev->left==p)//p为左
{
prev->left=p->left ? p->left:p->right;
}
else if(prev->right==p)//p为右
{
prev->right=p->left ? p->left:p->right;
}
free(p);
p=NULL;
}
return true;
}
void search_tree_order(Search_tree *t)//中序输出
{
if(t == NULL)
return ;
search_tree_order(t->left);
printf("%d ", t->value);
search_tree_order(t->right);
}
int main()
{
Search_tree *root = search_tree_create(11);
search_tree_insert(root, 8);
search_tree_insert(root, 15);
search_tree_insert(root, 4);
search_tree_insert(root, 9);
search_tree_insert(root, 6);
search_tree_insert(root, 18);
search_tree_order(root);
search_tree_delete(root, 11);
printf("\n");
search_tree_order(root);
search_tree_delete(root, 4);
printf("\n");
search_tree_order(root);
search_tree_destroy(root);
return 0;
}