【数据结构和算法】树表的查找算法(二叉排序树与平衡二叉树)

前诉:本文章的大致内容如下
在这里插入图片描述

二叉排序树

1、二叉排序树查的定义

二叉排序树有称为二叉搜索树,二叉查找树

  • 二叉排序树的定义:
    在这里插入图片描述

  • 二叉排序树的例子
    在这里插入图片描述

  • 二叉排序树性质:中序遍历非空的二叉排序树所得到的数据元素序列是一个按关键字排列的递增有序序列。

  • 二叉排序树结果出现的原因:二叉排序树的左节点的数字比根节点要小,而右节点的数字要比根节点要大。而中序遍历是先左子树,然后再跟,在右子树,所以便得到一个递增的有序序列。

2、二叉排序树查找算法

  • 二叉树的查找
    在这里插入图片描述
    分析:
      如上例子中,需要进行对105进行查找,首先105比122小,所以查找根节点的左子树99,然后发现99小于105,所以查找左子树的根节点99的右子树110,但110比105大,再查找110根节点的左子树,发现110的左子树就是105,查找成功。

  • 二叉排序树的存储结构

typedef struct{
	KeyType key;		//关键字项
	InfoType otherInfo;	//其他数据域
}ElemType;

typedef struct BSTNode{
	ElemType data;		//数据域
	struct BSTNode *lchild,*rchild;	//左右孩子指针
}BSTNode,*BSTree;

BSTree T;				//定义二叉排序树T
  • 算法思路
    在这里插入图片描述
  • 算法的代码实现
BSTree SearchBST(BSTree T,KeyType key){
	if( !T || key == T->data.key)	//如果树为空或者找到了,就返回这个T
		return T;					//为空就返回了NULL,否则返回找到的根节点
	else if(key < T->data.key)		//小于根节点,在左子树中继续查找
		return SearchBST(T->lchild,key);
	else							//大于根节点,在右子树中继续查找
		return SearchBST(T->rchild,key);
}

3、二叉排序树的算法分析

  • 二叉排序树的平均查找长度法分析
    在这里插入图片描述
    (其中,右边的二叉排序树退化成顺序查找法)
    在这里插入图片描述
    含有n个节点的二叉排序树的平均查找长度和树的形态有关

  • 二叉排序树的改进:针对树的形态会影响时间的复杂度,如何提高形态不均航的二叉排序树的查找效率?

解决方法:做“平衡化”处理,既尽量让二叉树的形状均衡。(也就是平衡二叉树)

4、二叉排序树的插入与生成

  • 二叉排序树的插入思路
    在这里插入图片描述
    (插入的元素一定在叶节点上)

  • 二叉排序树插入的例子
    在这里插入图片描述
    分析:
    以40为例,首先40与根节点45比较,但是小于根节点,所以进入到根节点的左孩子12,;40比左孩子12大,再进入根节点12的右孩子37,此时40比根节点37大而且根节点没有右孩子,所以40就成为了根节点的右孩子。

  • 二叉排序树插入算法

int InsertBST(BSTree T,KeyType key){
	if( !T) {				//如果树为空,说明应该在此空位插入
		T = (BSTree*)malloc(sizeof(BSTree));	//创建一个节点
		T->data.key = key;	//赋值
		..... 				//其他操作
		return 0;
	}
	else if( key == T->data.key)
		return -1;					//等于根节点,啥也不做,结束函数
	else if(key < T->data.key )
		InsertBST(T->lchild,key);	//小于根节点,递归查找左子树
	else 
		InsertBST(T->rchild,key);	//大于根节点,递归查找又子树
}

  • 二叉排序树的生成:从空树出发,进过一系列的查找,插入操作之后,可生成一棵二叉排序树
    在这里插入图片描述
    ps:
  1. 一个无序序列可以通过二叉排序树而变成一个有序序列,构造树的过程就是对无序序列进排序的过程。
  2. 插入的结点均为叶子结点,故无需移动其他结点,相当于在有序序列上插入记录而无需移动其他记录。
  3. 关键字的输入顺序的不同,建立的二叉排序树也可能将会不相同。
    在这里插入图片描述
    (二叉树的形态不一样,时间的复杂度也会不一样)

5、二叉排序树的删除

  • 情况1:被删除的结点是叶子结点,直接删除该结点

删前:
在这里插入图片描述
删后:
在这里插入图片描述

  • 情况2:被删除的结点只有左子树或者是右子树,用其左子树或者是右子树替换它(结点的替换)

删前:
在这里插入图片描述
删后:
**加粗样式**

  • 情况3:被删除的结点既有左子树也有右子树

删前:
在这里插入图片描述
找到被删关键字50的前驱节点40,并将其替换掉被删节点:
在这里插入图片描述
再原本的前驱节点40删除(如果40有左子树也有右子树就在同样重复上诉的步骤,再找到一40位跟结点的数中的左子树的前驱节点,再替换便可),而由于此处的40只有左子树,所以用40的左子树替换其便可。也就是30直接指向35。
在这里插入图片描述

  • 再一个例子
    在这里插入图片描述
  • 总结–树表的删除有两种方法:找出前驱节点替换,或找出后继节点替换。

平衡二叉树

1、平衡二叉树的定义

  • 平衡二叉树的定义(又称为AVL树)
    在这里插入图片描述
  • 平衡二叉树的平衡因子
    在这里插入图片描述
  • 平衡二叉树的例子
    在这里插入图片描述

2、平衡二叉树的四种调整方法

  • 平衡调整的四种类型
    在这里插入图片描述
  • 平衡调整4种类型的方法
    在这里插入图片描述
    ps:调整的原则为:
  1. 降低高度原则
  2. 保持二叉排序树的性质(左子树比根节点小,右子树比根节点大)

类型1:LL型

  • 类型1:LL型的调整过程
  1. 步骤1:开始:
    在这里插入图片描述
  2. 步骤二:B结点带着左子树α一起上升
    在这里插入图片描述
  3. 步骤三:A结点成为B的右孩子,B原来的右子树不要
    在这里插入图片描述
  4. 步骤四:原来B节点的右子树β作为A的左子树
    在这里插入图片描述
    示例:
    在这里插入图片描述

类型2:RR型

  • 类型2:RR型的调整过程
  1. 步骤一:开始
    在这里插入图片描述
  2. 步骤二:B节点带右子树β一起上升
    在这里插入图片描述
  3. 步骤三:A节点成为B的左孩子
    在这里插入图片描述
  4. 步骤四:原来B结点的左子树α作为A的右子树
    在这里插入图片描述
    示例:
    在这里插入图片描述
    调整结果:
    在这里插入图片描述

类型3:LR型

  • 类型3:LR型的调整过程
  1. 步骤一:开始
    在这里插入图片描述
  2. 步骤二:C结点穿过A,B结点上升
    在这里插入图片描述
  3. 步骤三:B结点成为C的左孩子,A结点成为C的右孩子
    在这里插入图片描述
  4. 步骤四:原来C结点的左孩子β作为B的右子树,原来C结点的右孩子γ作为A的左子树
    在这里插入图片描述
    示例:
    在这里插入图片描述

类型4:RL型

  • 类型4:RL型的调整过程

(演示略)示例:
在这里插入图片描述
结果如下:
在这里插入图片描述

3、平衡二叉树的构建

  • 构建一棵平衡二叉树的示例

在这里插入图片描述

构建过程如下所示:

  1. 插入7出现LR类型16,3,7,调整。
    在这里插入图片描述
  2. 插入9出现LL类型16,11,9,调整。
    在这里插入图片描述
  3. 插入26出现RR型7,11,16,调整。
    在这里插入图片描述
  4. 插入18出现RL型16,26,18,调整。
    在这里插入图片描述
  5. 插入14,没有失衡
    在这里插入图片描述
  6. 插入15出现LR型16,14,15,调整。
    在这里插入图片描述
  7. 如此,AVL树构建完成,这是查找性能最好的平衡二叉树

参考链接:https://space.bilibili.com/40323036

发布了34 篇原创文章 · 获赞 1 · 访问量 2273

猜你喜欢

转载自blog.csdn.net/weixin_44751294/article/details/104462316