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

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

二叉排序树


1、二叉排序树查的定义

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


  • 二叉排序树的定义:

image.png

  • 二叉排序树的例子

image.png

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


2、二叉排序树查找算法

  • 二叉树的查找

image.png

分析:

 如上例子中,需要进行对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


算法思路

image.png


算法的代码实现

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、二叉排序树的算法分析

二叉排序树的平均查找长度法分析

image.png


(其中,右边的二叉排序树退化成顺序查找法)

image.png

(含有n个节点的二叉排序树的平均查找长度和树的形态有关)

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


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


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

二叉排序树的插入思路

image.png

(插入的元素一定在叶节点上)


二叉排序树插入的例子

image.png


分析:

以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); //大于根节点,递归查找又子树
}


二叉排序树的生成:从空树出发,进过一系列的查找,插入操作之后,可生成一棵二叉排序树

image.png

ps:

  1. 一个无序序列可以通过二叉排序树而变成一个有序序列,构造树的过程就是对无序序列进排序的过程。
  2. 插入的结点均为叶子结点,故无需移动其他结点,相当于在有序序列上插入记录而无需移动其他记录。
  3. 关键字的输入顺序的不同,建立的二叉排序树也可能将会不相同。

(二叉树的形态不一样,时间的复杂度也会不一样)

image.png


5、二叉排序树的删除

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

删前:

image.png

删后:

image.png


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

删前:

image.png

删后:

image.png


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

删前:

image.png

找到被删关键字50的前驱节点40,并将其替换掉被删节点:

image.png

再原本的前驱节点40删除(如果40有左子树也有右子树就在同样重复上诉的步骤,再找到一40位跟结点的数中的左子树的前驱节点,再替换便可),而由于此处的40只有左子树,所以用40的左子树替换其便可。也就是30直接指向35。

image.png

再一个例子

image.png

总结–树表的删除有两种方法:找出前驱节点替换,或找出后继节点替换。


平衡二叉树


1、平衡二叉树的定义

平衡二叉树的定义(又称为AVL树)

image.png

平衡二叉树的平衡因子

image.png

平衡二叉树的例子

image.png


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

平衡调整的四种类型

image.png

平衡调整4种类型的方法

image.png

ps:调整的原则为:

降低高度原则

保持二叉排序树的性质(左子树比根节点小,右子树比根节点大)


类型1:LL型

类型1:LL型的调整过程

步骤1:开始:

image.png

步骤二:B结点带着左子树α一起上升

image.png

步骤三:A结点成为B的右孩子,B原来的右子树不要

image.png

步骤四:原来B节点的右子树β作为A的左子树

image.png

示例:

image.png


类型2:RR型

类型2:RR型的调整过程

步骤一:开始

image.png

步骤二:B节点带右子树β一起上升

image.png

步骤三:A节点成为B的左孩子

image.png

步骤四:原来B结点的左子树α作为A的右子树

image.png

示例:

image.png

调整结果:

image.png


类型3:LR型

类型3:LR型的调整过程

步骤一:开始

image.png

步骤二:C结点穿过A,B结点上升

image.png

步骤三:B结点成为C的左孩子,A结点成为C的右孩子

image.png

步骤四:原来C结点的左孩子β作为B的右子树,原来C结点的右孩子γ作为A的左子树

image.png

示例:

image.png


类型4:RL型

类型4:RL型的调整过程

(演示略)示例:

image.png

结果如下:

image.png


3、平衡二叉树的构建

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

image.png


构建过程如下所示:

  1. 插入7出现LR类型16,3,7,调整。

image.png

  1. 插入9出现LL类型16,11,9,调整。

image.png

  1. 插入26出现RR型7,11,16,调整。

image.png

  1. 插入18出现RL型16,26,18,调整。

image.png

  1. 插入14,没有失衡

image.png

  1. 插入15出现LR型16,14,15,调整。

image.png

  1. 如此,AVL树构建完成,这是查找性能最好的平衡二叉树


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

目录
相关文章
|
29天前
|
机器学习/深度学习 算法 数据挖掘
K-means聚类算法是机器学习中常用的一种聚类方法,通过将数据集划分为K个簇来简化数据结构
K-means聚类算法是机器学习中常用的一种聚类方法,通过将数据集划分为K个簇来简化数据结构。本文介绍了K-means算法的基本原理,包括初始化、数据点分配与簇中心更新等步骤,以及如何在Python中实现该算法,最后讨论了其优缺点及应用场景。
97 4
|
2月前
|
存储 人工智能 算法
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
95 3
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
|
1月前
|
算法
数据结构之博弈树搜索(深度优先搜索)
本文介绍了使用深度优先搜索(DFS)算法在二叉树中执行遍历及构建链表的过程。首先定义了二叉树节点`TreeNode`和链表节点`ListNode`的结构体。通过递归函数`dfs`实现了二叉树的深度优先遍历,按预序(根、左、右)输出节点值。接着,通过`buildLinkedList`函数根据DFS遍历的顺序构建了一个单链表,展示了如何将树结构转换为线性结构。最后,讨论了此算法的优点,如实现简单和内存效率高,同时也指出了潜在的内存管理问题,并分析了算法的时间复杂度。
52 0
|
3天前
|
存储 运维 监控
探索局域网电脑监控软件:Python算法与数据结构的巧妙结合
在数字化时代,局域网电脑监控软件成为企业管理和IT运维的重要工具,确保数据安全和网络稳定。本文探讨其背后的关键技术——Python中的算法与数据结构,如字典用于高效存储设备信息,以及数据收集、异常检测和聚合算法提升监控效率。通过Python代码示例,展示了如何实现基本监控功能,帮助读者理解其工作原理并激发技术兴趣。
41 20
|
27天前
|
数据采集 存储 算法
Python 中的数据结构和算法优化策略
Python中的数据结构和算法如何进行优化?
|
1月前
|
算法
数据结构之路由表查找算法(深度优先搜索和宽度优先搜索)
在网络通信中,路由表用于指导数据包的传输路径。本文介绍了两种常用的路由表查找算法——深度优先算法(DFS)和宽度优先算法(BFS)。DFS使用栈实现,适合路径问题;BFS使用队列,保证找到最短路径。两者均能有效查找路由信息,但适用场景不同,需根据具体需求选择。文中还提供了这两种算法的核心代码及测试结果,验证了算法的有效性。
102 23
|
27天前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
53 5
|
26天前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
57 1
|
1月前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
89 16
|
1月前
|
算法
树的遍历算法有哪些?
不同的遍历算法适用于不同的应用场景。深度优先搜索常用于搜索、路径查找等问题;广度优先搜索则在图的最短路径、层次相关的问题中较为常用;而二叉搜索树的遍历在数据排序、查找等方面有重要应用。
39 2