【数据结构】建立二叉排序树和二叉排序树的插入、查找、删除操作

二叉排序树的概念

二叉排序树(Binary Sort Tree),又称为二叉查找树,是一种特殊的二叉树。它或者是一棵空树,或者是具有下列性质的二叉树:

  • 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值。
  • 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值。
  • 它的左、右子树也分别为二叉排序树。
    换句话说,二叉排序树中,每个节点的值都大于其左子树中任意节点的值,且小于其右子树中任意节点的值。

在这里插入图片描述

二叉排序树的结构

typedef struct BST_Node
{
	struct BST_Node* Left; // 指向当前节点左孩子
	struct BST_Node* Right; // 指向当前节点右孩子
	char data; // 当前节点数据域
}BST_Node, * BST_Tree;

建立二叉树

void CreateBST(BST_Tree* T, int a[], int n)
{
	for (int i = 0; i < n; i++)
	{
		InsertBST(T, a[i]);
	}
}

插入结点

插入新元素时,可以从根节点开始,遇键值较大者就向左,遇键值较小者就向右,一直到叶子节点在进行插入。

void InsertBST(BST_Tree* root, int value)
{
    //如果没有就创建
    if (!(*root))
    {
        *root = malloc(sizeof(BST_Node));
        if (!*root) exit(-1);
        (*root)->data = value;
        (*root)->Left = (*root)->Right = NULL;
        return;
    }
    if (value > (*root)->data)
        InsertBST(&((*root)->Right), value);
    else if (value < (*root)->data)
        InsertBST(&((*root)->Left), value);
    else
        return;
}

查找

查找最小

从根节点一直往左走,直到最左边的就是最小

在这里插入图片描述

BST_Tree SerchMin(BST_Tree root)
{
    if (!root)
        return NULL;
    if (!(root->Left))
        return root;
    else
        return SerchMin(root->Left);
   
}

查找最大

从根节点一直往右走,直到最右边的就是最小
在这里插入图片描述

BST_Tree SerchMax(BST_Tree root)
{
    if (!root)
        return NULL;
    if (!(root->Right))
        return root;
    else
        return SerchMax(root->Right);
}

在这里插入图片描述

查找

从根节点出发,遇到键值大的节点就向这个节点的左孩子方向查找,遇到键值小的就向则个节点的右孩子方向查找。

BST_Tree Search(BST_Tree root,int value)
{
    if (root == NULL)
        return NULL;
    if (value > root->data) //查找右子树  
        return Search(root->Left, value);
    else if (value < root->data) //查找左子树  
        return Search(root->Right, value);
    else
        return root;
   
}

删除

1 若p有左子树,找到其左子树的最右边的叶子结点r,把p的右子树作为r的右子树;用p的左孩子取代p;
2 若p没有左子树,直接用p的右孩子取代它。

有些资料在删除的时候是分叶子结点,非叶子结点(一个孩子),非叶子结点(两个孩子),根结点讨论

BST_Tree DeleteNode(BST_Tree p)
{
    if (p->Left)
    {
        BST_Tree r = p->Left;
        while (r->Right)
        {
            r = r->Right;
        }
        r->Right = p->Right;
        BST_Tree t=malloc(sizeof(BST_Node));
        t = p->Left;
        free(p);

        return t;
    }
    else
    {
        BST_Tree t=malloc(sizeof(BST_Node));
        t = p->Right;
        free(p);

        return t;

    }
}
BST_Tree DeleteTree(BST_Tree* p, int x)
{
    if (!(*p))
        return NULL;
    else
    {
        if (x == (*p)->data)
            (*p) =DeleteNode((*p));
        else if (x > (*p)->data)
            (*p)->Right=DeleteTree((*p)->Right, x);
        else
            (*p)->Left=DeleteTree((*p)->Left, x);
    }
    return (*p);
}

注意
DeleteTree的参数是BST_Tree的指针,因为只有传入指针才能实现对传入参数的真正的修改。
也可以不用传人指针,不过要接收函数的返回值。

int a[13] = { 23,26,4,44,32,17,20,13,14,15,45,1,5 };
BST_Tree tree=NULL;
CreateBST(&tree, a, 13);
/*tree=DeleteTree(tree,23);
DeleteTree(&tree,23);*/

遍历

前序遍历

void PreOrderTraversal(BST_Tree Tree)
{
    if (!Tree)
        return;
    else
    {
        printf("%3d", Tree->data);
        PreOrderTraversal(Tree->Left);
        PreOrderTraversal(Tree->Right);
    }
}

中序遍历

void InOrderTraversal(BST_Tree Tree)
{
    if (!Tree)
        return;
    else
    {
        InOrderTraversal(Tree->Left);
        printf("%3d", Tree->data);
        InOrderTraversal(Tree->Right);
    }
}

后序遍历

void PostOrderTraversal(BST_Tree Tree)
{
    if (!Tree)
        return;
    else
    {
        PostOrderTraversal(Tree->Left);
        PostOrderTraversal(Tree->Right);
        printf("%c ", Tree->data);
    }
}

删除测试

删除叶子结点5

在这里插入图片描述
运行结果
在这里插入图片描述
没问题,符合要求

删除结点26

若p没有左子树,直接用p的右孩子取代它。
在这里插入图片描述

运行结果
在这里插入图片描述

没问题,符合要求

删除节点17

若p有左子树,找到其左子树的最右边的叶子结点r,把p的右子树作为r的右子树;用p的左孩子取代p;
在这里插入图片描述
运行结果
在这里插入图片描述

没问题,符合要求

删除根结点

若p有左子树,找到其左子树的最右边的叶子结点r,把p的右子树作为r的右子树;用p的左孩子取代p;
在这里插入图片描述
运行结果
在这里插入图片描述
没问题,符合要求

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值