07-7.3.1 二叉排序树(BST)

👋 Hi, I’m @Beast Cheng
👀 I’m interested in photography, hiking, landscape…
🌱 I’m currently learning python, javascript, kotlin…
📫 How to reach me --> 458290771@qq.com


喜欢《数据结构》部分笔记的小伙伴可以订阅专栏,今后还会不断更新。🧑‍💻
感兴趣的小伙伴可以点一下订阅、收藏、关注!🚀
谢谢大家!🙏

定义

又称 二叉查找树(BST,Binary Search Tree)
一棵二叉树或是空二叉树,或者是具有如下性质的二叉树:

  • 左子树上所有节点的关键字均小于根节点的关键字;
  • 右子树上所有结点的关键字均大于根结点的关键字。
  • 左子树和右子树又各是一棵二叉排序树
    左子树结点值 < 根结点值 < 右子树结点值
    根据中序遍历,可以得到一个递增的有序序列

查找

  • 若树非空,目标值与根结点的值比较;
  • 若相等,则查找成功;
  • 若小于根结点,则在左子树上查找,否则在右子树上查找
  • 查找成功,返回结点指针;查找失败,返回NULL
typedef struct BSTNode{
	int key;
	struct BSTNode *lchild, *rchild;
} BSTNode, *BSTree;

// 在二查排序树中查找值为 key 的结点
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;
}

// 在二查排序树中查找值为 key 的结点(递归实现)
BSTNode *BSTSearch(BSTree T, int key){
	if(T == NULL)
		return NULL;  // 查找失败
	if(key == T -> key)
		return T;  // 查找成功
	else if(key < T -> key)
		return BSTSearch(T -> lchild, key);  // 在左子树中查找
	else
		return BSTSearch(T -> rchild, key);  // 在右子树中查找
}

上面的最坏空间复杂度 O ( 1 ) O(1) O(1)
下面的最坏空间复杂度 O ( h ) O(h) O(h)

插入

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

int BST_Insert(BSTree &T, int k){
	if(T == NULL){  // 原树为空
		T = (BSTree) malloc (sizeof(BSTNode));
		T -> key = k;
		T -> lchild = T -> rchild = NULL;
		return 1;  // 返回 1,插入成功
	}
	else if(k == T -> key)  // 树中存在相同关键字的结点,插入失败
		return 0;
	else if(k < T -> key)  // 插入到T的左子树
		return BST_Insert(T -> lchild, k);
	else  // 插入到T的右子树
		return BST_Insert(T -> rchild, k);
}

构造

// 按照 str[] 中的关键字序列建立二叉排序树
void Create_BST(BSTree &T, int str[], int n){
	T = NULL;  // 初始时T为空树
	int i = 0;
	while(i < n){  // 依次将每个关键字插入到二叉排序树中
		BST_Insert(T, str[i]);
		i ++;
	}
}

不同的关键字序列可能得到同款二叉排序树,也可能得到不同款

删除

先搜索找到目标节点:

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

查找效率分析

查找成功

查找长度:在查找运算中,需要对比关键字的次数。反映了查找操作时间复杂度
查找成功平均查找长度ASL
查找操作时间复杂度

  • 最好情况:n 个结点的二叉树最小高度为 [ l o g 2 n ] + 1 [log_2n]+1 [log2n]+1 ,平均查找长度 = O ( l o g 2 n ) =O(log_2n) =O(log2n)
  • 最坏情况:每个结点只有一个分支,树高 h = 结点数 n,平均查找长度 = O ( n ) =O(n) =O(n)

查找失败

看最尾端的叶子节点有几个(假设是 n ),那么就会出现 n 种情况是查找失败的,概率是 1/9

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Beast Cheng

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

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

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

打赏作者

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

抵扣说明:

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

余额充值