数据结构——二叉排序树

——本节内容为Bilibili王道考研《数据结构》P51视频内容笔记。


目录

1.定义

2.二叉排序树的查找

3.二叉排序树的插入

4.二叉排序树的构造

5.二叉排序树的删除

6.查找效率分析


1.定义

(1)二叉排序树,又称二叉查找树。一棵二叉树或是空二叉树,或是具有如下性质的二叉树:
        ①左子树上所有结点的关键字均小于根结点的关键字;
        ②右子树上所有结点的关键字均大于根结点的关键字;
        ③左子树和右子树又各是一棵二叉排序树。

(2)由于左子树结点值<根结点值<右子树结点值,所以进行中序遍历就可以得到一个递增的有序序列。

(3)图示:

 (4)二叉排序树可用于元素的有序组织、搜索。


2.二叉排序树的查找

(1)二叉排序树结点结构体:

typedef struct BSTNode {
	int key;
	struct BSTNode* lchild, * rchild;
}BSTNode,*BSTree;

(2)查找操作:

        ①若树非空,目标值与根结点的值比较:若相等则查找成功;若小于根结点,则在左子树上查找,否则在右子树上查找。
        ②查找成功返回结点指针,失败返回NULL。

(3)代码实现:

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;
}

最坏空间复杂度O(1)。

(4)递归实现:

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(h)。

(5)如果查找失败,则最终会落在某一个叶子结点的左右孩子也就是NULL,如图:


3.二叉排序树的插入

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

(2)代码实现:

//在二叉排序树插入关键字为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);
}

最坏空间复杂度O(h)。


4.二叉排序树的构造

(1)构造一个二叉排序树说白了就是往这棵树里不断进行二叉排序树的插入操作。

(2)代码实现:

//按照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++;
	}
}

(3)注意:不同的关键字序列可能得到同款二叉排序树,也可能得到不同款二叉排序树。


5.二叉排序树的删除

(1)操作步骤:

先搜索找到目标结点:
        ①若被删除结点z是叶结点,则直接删除,不会破坏二叉排序树的性质。
        ②若结点z只有一棵左子树或右子树,则让z的子树成为z父结点的子树,替代z的位置。
        ③若结点z有左、右两棵子树,则令z的直接后继(或直接前驱)替代z,然后从二叉排序树中删去这个直接后继(直接前驱),这样就转换成了①或②的情况。

(2)

        z的后继:z的右子树中最左下的结点(该结点一定没有左子树)
        z的前驱:z的左子树中最右下的结点(该结点一定没有右子树)


6.查找效率分析

(1)查找长度:在查找运算中,需要对比关键字的次数称为查找长度,反映了查找操作时间复杂度。

(2)查找成功的平均查找长度ASL=各个结点查找长度之和除以总结点数,如下图:

(3)查找失败的平均查找长度ASL=含有空子树的结点所在的层数*空子树结点的个数,如下图:

(4)如果一棵树高h,那么找到最下层的一个结点需要对比h次,所以二叉排序树的查找效率很大程度上取决于这棵树的高度。

之前提到,对于n个结点的二叉树的最小高度为\left \lfloor log_{2}^{}\textrm{}n \right \rfloor+1, 此时为最好的情况,即这棵树是”一棵胖胖的树“,平均查找长度=O\left ( log_{2}^{}\textrm{}n \right )

最坏的情况是,每个结点都只有一个分支,即这棵树是”一棵杆儿瘦的树“,平均查找长度=O(n)。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值