数据结构:二叉搜索树

一、查找的一些问题

  • 查找分为静态查找和动态查找,前者的查找内容本身和数量不发生改变,后者则会出现删除、插入等操作,对查找内容本身和数量造成影响。
  • 那么针对动态查找的问题,二叉搜索树是一个较好的解决方法。

二、什么是二叉搜索树?

  • 二叉搜索树是一颗二叉树,它可以为空,如果不为空的话需要满足以下性质:
    1. 非空左子树所有键值小于其根节点的键值
    2. 非空左子树所有键值大于其根节点的键值
    3. 左、右子树都是二叉搜索树

三、二叉搜索树可能包含的函数

  • 查找(包括查找特定值,最大值最小值并返回地址)
//代码并非具体语言
function Find(ElementType X,BinTree BST){
    if (!BST)
        return NULL;
    if(X > BST->Data)
        return Find(X,BST->Right); //查找右子树
    else if(X < BST->Data)
        return Find(X,BST->Left); //查找左子树
    else
        return BST; //找到要查找的节点,返回节点地址
}

//非递归方式:
function AnotherFind(ElementType X,BinTree BST){
    while(BST){
        if(X > BST->Data)
            BST = BST->Right;  //查找右子树
        else if(X < BST->Data)
            BST = BST->Left;    //查找左子树
        else
            return BST; //找到要查找的节点,返回节点地址
    }
    return NULL //未查找到,返回空
}
  • 查找最大和最小元素(属于查找)
    1. 最大元素一定在树的最右分支的端节点上
    2. 最小元素一定在树的最左分支的端节点上
//查找最小,使用了递归方法
function MinFind(BinTree BST){
    if(!BST)
        return NULL;
    else if(!BST->Left) //不存在左节点
        return BST //找到最左节点并返回
    else //存在左节点
        return MinFind(BST->Left) //查找左节点
}

//查找最大,使用了迭代方法
function MaxFind(BinTree BST){
    if(BST)
        while(BST->Right)
            BST = BST->Right;
    return BST;
}
  • 插入、删除
    • 二叉搜索树的插入和删除的关键问题在于要找到需要修改的节点位置,这类似于查找的过程,可以采用与查找类似的方法。
    • 删除操作存在三种情况:
      1. 要删除的节点是叶子节点
        这种情况直接删除节点即可
      2. 要删除的节点有一个子节点与他链接
        这种情况可将子节点连接至删除节点的父节点
      3. 要删除的节点有两个子节点与他链接
        这种情况我们可以使用一个节点来替代被删除节点:右子树的最小元素或者左子树的最大元素
//插入
BinTree Insert(ElementType X,BinTree BST){
    if(!BST){ //树或节点为空
        BST = malloc(sizeof(struct TreeNode)); //生成一个节点
        BST->Data = X;
        BST->Left = BST->Right = NULL;
    }

    else{ //查找插入节点
        if(X < BST->Data)
            BST->Left = Insert(X,BST->Left); //递归查找并插入
        else if (X > BST->Data)
            BST->Right = Insert(X,BST->Right); 
    }
    
    return BST;
}
//删除
BinTree Delete(ElementType X,Bintree BST){
    BinTree Position;
    if(!BST) //未找到要删除的元素
        printf("未找到!");
    else if(X < BST->Data)
        BST->Left = Delete(X,BST->Left); //在左节点找并删除
    else if(X > BST->Data)
        BST->Right = Delete(X,BST->Right); //在右节点找并删除
    else //找到要删除的节点
        if(BST->Left && BST->Right){ //存在左右子节点
            Position = MinFind(BST->Right);
            BST->Data = Position->Data;
            BST->Right = Delete(BST->Data,BST->Right);
        }else{ //被删除的节点有一个或没有子节点
            Position = BST;
            if(!BST->Left){ //有右节点或没有节点
                BST = BST->Right;
            }else if(!BST->Right){ //有左节点或没有节点
                BST = BST->Left;
            }
            free(Position); //清空Position
        }
    return BST; //返回修改完成的树
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值