数据结构与算法之二叉排序树

定义

二叉排序树,又称二叉查找树 (BST)
一颗二叉树或者空二叉树,或者是具有如下性质的二叉树:

  1. 左子树上所有的结点的关键字均小于根节点的关键字。
  2. 右子树上所有的结点的关键字均大于根节点的关键字。
  3. 左子树和右子树有各是一颗二叉排序树。

左子树结点值<根节点<右子树结点值
进行中序遍历,可以得到一个递增的有序序列
因此二叉排序树可用于元素的有序组织、搜索

二叉排序树的查找

左子树结点值<根节点值<右子树结点值
若树非空,目标值与根节点的值比较:

  • 若相等,则查找成功。
  • 若小于根节点,则在左子树上查找,否则在右子树上查找。
    查找成功,返回结点指针;查找失败返回 NULL
/**  
 * 二叉搜索树  
 * @author five-five 
 * @created 2022/6/2 
 * 
 **/
#include "stdio.h"  
#include "stdlib.h"  
#include "stdbool.h"  
  
typedef struct BSTNode {  
    int key;  
    struct BSTNode *lChild;  
    struct BSTNode *rChild;  
} BSTNode, *BSTree;  

/**
 * 非递归实现
 */
BSTNode *BST_Search(BSTree T, int key) {  
    while (T != NULL && key != T->key) {//若树空或等于根节点值,则结束循环  
        if (key < T->key) { //小于,则在左子树查找  
            T = T->lChild;  
        } else {//大于,则在右子树查找  
            T = T->rChild;  
        }  
    }    return T;  
}
/**
 * 递归实现
 */
BSTNode *BST_Search(BSTree T, int key) {  
    if (T == NULL) {  
        return NULL;  
    }  
    if (key==T->key) {  
        return T;  
    }  
    if (key>T->key) {  
        BST_Search(T->rChild, key);  
    }  
    if (key<T->key) {  
        BST_Search(T->lChild, key);  
    }  
    return NULL;  
}

二叉排序树的插入

若原二叉排序树为空,则直接插入结点;否则,若关键字 k 小于根节点值,则插入到左子树,若关键字 k 大于根节点值,则插入到右子树。

/**  
 * 在二叉排序树插入关键字为k的新节点  
 * @param T * @param k * @return */int BSt_Insert(BSTree *T, int k) {  
    if (*T == NULL) {  
        BSTree cur = (BSTree) malloc(sizeof(BSTNode));  
        cur->key = k;  
        cur->rChild = NULL;  
        cur->lChild = cur->rChild;  
        (*T) = cur;  
        return 0;  
    }  
    BSTree tree = *T;  
    if (k == tree->key) {//存在相同结点,插入失败  
        return -1;  
    }  
    if (k > tree->key) {//大于,右子树去找  
        struct BSTNode *rChild = (*T)->rChild;  
        return BSt_Insert(&rChild, k);  
    } else {//小于,左子树去找  
        struct BSTNode *lChild = (*T)->lChild;  
        return BSt_Insert(&lChild, k);  
    }  
}

二叉排序树的构造

按照数组依次构建二叉排序树 (使用上面 二叉排序树的插入来实现)

注意:不同关键字序列可能得到同款二叉排序树

/**  
 * 二叉排序树的构建  
 * @param T 排序树结点,也就是要操作的对象  
 * @param arr 值数组  
 * @param length 数组长度  
 */
void Create_BST(BSTree *T, int *arr, int length) {  
    (*T) = NULL;  
    int i = 0;  
    while (i < length) {  
        BST_Insert(T, arr[i]);  
        i++;  
    }  
  
}

二叉排序树的删除

  1. 搜索 找到目标结点:
    1. 若被删除结点 z 是叶子节点,则直接删除,不会破坏二叉排序树的性质
    2. 若结点 z 只有一颗左子树或右子树,则让 z 的子树成为 z 父节点的子树,替代 z 的位置
    3. 若结点 z 有左右两颗子树,则令 z 的直接后继 (或直接前驱) 替代 z,然后从二叉排序树中删去这个直接后继 (或直接前驱),这样就转换成了第一或第二种情况。
      1. 使用直接后继来替换 z 结点
        1. z 的后继z 的右子树最左下结点 (该节点一定没有左子树)
      2. 使用直接前驱来替换 z 结点
        1. z 的前驱z 的左子树最右下结点 (该节点一定没有右子树)

总结:

二叉排序树的中序遍历是有序的,且为升序。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

five-five

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值