二叉搜索树

二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。
算法实现

1 二叉排序树的查找算法

2 在二叉排序树插入结点的算法

3 在二叉排序树删除结点的算法

递归实现 :

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>


typedef struct BSTreeNode
{
    int key;//不允许重复,不允许更改
    struct BSTreeNode *pLeft;
    struct BSTreeNode *pRight;
}BSTreeNode;

//递归实现
//查找
//是否找到:1 找到, 0 没找到
int FindR(BSTreeNode *pRoot, int key)
{
    if (pRoot == NULL)
    {
        return 0;
    }
    if (key == pRoot->key)
    {
        return 1;
    }
    if (key < pRoot->key)
    {
        return FindR(pRoot->pLeft, key);
    }
    return FindR(pRoot->pRight, key);

}

BSTreeNode * CreateNode(int key)
{
    BSTreeNode *pNode = (BSTreeNode *)malloc(sizeof(BSTreeNode));
    assert(pNode);
    pNode->key = key;
    pNode->pLeft = pNode->pRight = NULL;
    return pNode;

}

//插入
//0表示成功    -1表示失败
int InsertR(BSTreeNode **pRoot, int key)
{
    if (*pRoot == NULL)
    {
        *pRoot = CreateNode(key);
        return 0;
    }
    if (key == (*pRoot)->key)
    {
        return -1;
    }
    if (key < (*pRoot)->key)
    {
        return InsertR(&(*pRoot)->pLeft, key);
    }
    return InsertR(&(*pRoot)->pRight, key);

}
//删除  0表示成功,-1表示失败
int RemoveR(BSTreeNode **pRoot, int key)
{
    if (*pRoot == NULL)
    {
        return -1;
    }
    if (key < (*pRoot)->key)
    {
        return  RemoveR(&(*pRoot)->pLeft, key);
    }
    else if (key>(*pRoot)->key)
    {
        return RemoveR(&(*pRoot)->pRight,key);
    }
    //处理删除 
    if ((*pRoot)->pLeft == NULL)//左子树为空
    {
        *pRoot = (*pRoot)->pRight;
        return 0;
    }
    if ((*pRoot)->pRight == NULL)//右子树为空
    {
        *pRoot = (*pRoot)->pLeft;
        return 0;
    }
    //左右子树都不为空,找右子树中的最小孩子替换删除
    /*BSTreeNode *pSwap = (*pRoot)->pRight;
    while (pSwap->pLeft != NULL)
    {
        pSwap= pSwap->pLeft;
    }
    (*pRoot)->key = pSwap->key;
    RemoveR(&(*pRoot)->pRight, pSwap->key);
    return 0;*/
    //找左子树中最大的孩子替换删除
    BSTreeNode *pSwap = (*pRoot)->pLeft;
    while (pSwap->pRight != NULL)
    {
        pSwap = pSwap->pRight;
    }
    (*pRoot)->key = pSwap->key;
    RemoveR(&(*pRoot)->pLeft, pSwap->key);
    return 0;
}

非递归实现:

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>


typedef struct BSTreeNode
{
    int key;//不允许重复,不允许更改
    struct BSTreeNode *pLeft;
    struct BSTreeNode *pRight;
}BSTreeNode;
//查找
//是否找到:1 找到 0 没找到
int Find(BSTreeNode *pRoot, int key)
{
    BSTreeNode *pNode = pRoot;
    while (pNode != NULL)
    {
        if (key == pNode->key)
        {
            return 1;
        }
        else if (key < pNode->key)
        {
            pNode = pNode->pLeft;
        }
        else
        {
            pNode = pNode->pRight;
        }
    }
    return 0;
}   

BSTreeNode * CreateNode(int key)
{
    BSTreeNode *pNode = (BSTreeNode *)malloc(sizeof(BSTreeNode));
    assert(pNode);
    pNode->key = key;
    pNode->pLeft = pNode->pRight = NULL;

    return pNode;

}
//插入
//0表示成功    -1表示失败
int Insert(BSTreeNode **pRoot, int key)
{
    BSTreeNode *pNode =*pRoot;
    BSTreeNode *pParent = NULL;
    while (pNode != NULL)
    {
        if (key == pNode->key)
        {
            return -1;
        }
        else if (key < pNode->key)
        {
            pParent = pNode;
            pNode = pNode->pLeft;
        }
        else 
        {
            pParent = pNode;
            pNode = pNode->pRight;
        }
    }
    if (pParent == NULL)//空树
    {
        *pRoot = CreateNode(key);
        return 0;
    }
    //左还是右?
    if (key < pParent->key)
    {
         pParent->pLeft=CreateNode(key);
    }
    else if (key>pParent->key)
    {
         pParent->pRight=CreateNode(key);
    }

    return 0;
}
//删除 0表示成功,-1表示失败
int Remove(BSTreeNode **pRoot, int key)
{
    BSTreeNode *pNode = *pRoot;
    BSTreeNode *pParent = NULL;
    BSTreeNode *pSwap = NULL;
    BSTreeNode *pSwapParent = NULL;
    while (pNode != NULL)
    {
        //处理删除
        if (key==pNode->key)
        {
            if (pNode->pLeft == NULL)//要删除的结点左孩子为空
            {
                if (pNode == *pRoot)//要删除的为根节点
                {
                    *pRoot = pNode->pRight;
                    free(pNode);
                    return 0;
                }
                else
                {
                    if (pNode == pParent->pLeft)//要删除的为父亲的左孩子
                    {
                        pParent->pLeft = pNode->pRight;
                    }
                    else//要删除的为父亲的右孩子
                    {
                        pParent->pRight = pNode->pRight;
                    }
                    free(pNode);
                    return 0;
                }
            }
            else if (pNode->pRight == NULL)//要删除的结点右孩子为空
            {
                if (pNode == *pRoot)
                {
                    *pRoot = pNode->pLeft;
                    free(pNode);
                    return 0;
                }
                else
                {
                    if (pNode = pParent->pLeft)
                    {
                        pParent->pLeft = pNode->pLeft;
                    }
                    else
                    {
                        pParent->pRight = pNode->pLeft;
                    }
                    free(pNode);
                    return 0;
                }

            }
            else//要删除的结点左,右孩子都不为空.用右子树的最小孩子替换删除
            {
                pSwap = pNode->pRight;
                while (pSwap->pLeft != NULL)//找右子树的左子树
                {
                    pSwapParent = pSwap;
                    pSwap = pSwap->pLeft;
                }
                pNode->key = pSwap->key;//将找到左子树的最小孩子(pSwap)与要删除的结点(pNode)进行数据交换
                //删除pSwap结点
                if (pSwap == pNode->pRight)
                {
                    pNode->pRight = pSwap->pRight;
                }
                else
                {
                    pSwapParent->pLeft = pSwap->pRight;
                }
                free(pSwap);
                return 0;

            }

        }
        else if (key <= pNode->key)
        {
            pParent = pNode;
            pNode = pNode->pLeft;
        }
        else
        {
            pParent = pNode;
            pNode = pNode->pRight;
        }
    }
    return -1;
}

例:如图演示二叉搜索树的8种删除情况:
这里写图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值