二叉搜索树 c 语言实现

一、介绍

二叉搜索树(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;
}


  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值