数据结构——平衡二叉树

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


目录

一、定义

二、结构体定义

三、插入操作

四、查找效率分析


一、定义

1.平衡二叉树,简称平衡树(AVL树),树上任一结点的左子树和右子树的高度之差不超过1;

2.结点的平衡因子=左子树高-右子树高;

3.平衡二叉树结点的平衡因子的值只可能是-1、0、1;

4.只要有任一结点的平衡因子绝对值大于1,就不是平衡二叉树。


二、结构体定义

1.key为数据域;

2.balance为平衡因子。

typedef struct AVLNode {
 int key;
 int balance;
 struct AVLNode* lchild, * rchild;
}AVLNode,*AVLTree;

三、插入操作

在二叉树中插入新结点后,如何保持平衡?

1.从插入点往回找到第一个不平衡结点,调整以该结点为根的子树(即每次调整的对象都是“最小不平衡子树”);

2.在插入操作中,只要将最小不平衡子树调整平衡,则其他祖先结点都会恢复平衡;

3.要满足:(1)恢复平衡;(2)保持二叉排序树的特性(左子树结点值<根结点值<右子树结点值),分为以下四种情况:

①LL:在A的左孩子的左子树插入导致不平衡:

        LL平衡右旋(右单旋转)。由于在结点A的左孩子(L)的左子树(L)上插入了新结点,A的平衡因子由1增至2,导致以A为根的子树失去平衡,需要一次向右的旋转操作。将A的左孩子B向右上旋转代替A成为根结点,将A结点向右下旋转成为B的右子树的根结点,而B的原右子树则作为A结点的左子树。

//f.lchild = p.rchild;
//p.rchild = f;
//gf.lchild / rchild = p;

②RR:在A的右孩子的右子树插入导致不平衡:

        RR平衡左旋(左单旋转)。由于在根结点A的右孩子(R)的右子树(R)上插入了新结点,A的平衡因子由-1减至-2.导致以A为根的子树失去平衡,需要一次向左的旋转操作。将A的右孩子B向左上旋转代替A成为根结点,将A结点向左下旋转成为B的左子树的根结点,而B的原左子树则作为A结点的右子树。(操作同LL类似,省略图示)

//f.rchild = p.lchild;
//p.lchild = f;
//gf.lchild / rchild = p;


③RL:在A的右孩子的左子树插入导致不平衡:

        RL平衡旋转(先右后左双旋转)。由于在A的右孩子(R)的左子树(L)上插入新结点,A的平衡因子由-1减至-2,导致以A为根的子树失去平衡,需要进行两次旋转操作,先右旋转后左旋转。先将A结点的右孩子B的左子树的根结点C向右上旋转提升到B结点的位置,然后再把该C结点向左上旋转提升到A结点的位置。

④LR:在A的左孩子的右子树插入导致不平衡:

         LR平衡旋转(先左后右双旋转)。由于在A的左孩子(L)的右子树(R)上插入新结点,A的平衡因子由1增至2,导致以A为根的子树失去平衡,需要进行两次旋转操作,先左旋转后右旋转。先将A结点的左孩子B的右子树的根结点C向左上旋转提升到B结点的位置, 然后再把该C结点向右上旋转提升到A结点的位置。

4.一步到位操作

        RL 和 LR 两种操作可以由两步合并为一步,总结:先写C结点作为根结点,其左孩子为左旋操作所替代的结点,右孩子为右旋操作所替代的结点,将C结点的左子树放到左旋替代的结点的右子树的位置,将C结点的右子树放到右旋替代的结点的左子树的位置,其他都不变。

5.只有左孩子才有可能进行右旋操作,只有右孩子才有可能进行左旋操作;

6.在插入操作中,只要将最小不平衡子树调整平衡,则其他祖先结点都会恢复平衡;因为插入操作导致“最小不平衡子树”高度+1,经过调整后高度恢复,而平不平衡就是树高h决定的。


四、查找效率分析

1.若树高为h,则最坏情况下,查找一个关键字最多需要对比h次,即查找操作的时间复杂度不可能超过O(h);

2.假设以 n_{h} 表示深度为 h 的平衡树中含有的最少结点数,则有:

n_{0}=0,n_{1}=1,n_{2}=2,n_{h}=n_{h-1}+n_{h-2}+1

3.基于上述公式可以证明:含有n个结点的平衡二叉树的最大深度为 O(log_{2}^{}n\textrm{}) ,平衡二叉树的平均查找长度(查找操作的时间复杂度)为 O(log_{2}^{}n\textrm{}) 。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 什么是二叉树? 二叉树是一种树形结构,其中每个节点最多有两个子节点。一个节点的左子节点比该节点小,右子节点比该节点大。二叉树通常用于搜索和排序。 2. 二叉树的遍历方法有哪些? 二叉树的遍历方法包括前序遍历、中序遍历和后序遍历。前序遍历是从根节点开始遍历,先访问根节点,再访问左子树,最后访问右子树。中序遍历是从根节点开始遍历,先访问左子树,再访问根节点,最后访问右子树。后序遍历是从根节点开始遍历,先访问左子树,再访问右子树,最后访问根节点。 3. 二叉树的查找方法有哪些? 二叉树的查找方法包括递归查找和非递归查找。递归查找是从根节点开始查找,如果当前节点的值等于要查找的值,则返回当前节点。如果要查找的值比当前节点小,则继续在左子树中查找;如果要查找的值比当前节点大,则继续在右子树中查找。非递归查找可以使用栈或队列实现,从根节点开始,每次将当前节点的左右子节点入栈/队列,直到找到要查找的值或者栈/队列为空。 4. 二叉树的插入与删除操作如何实现? 二叉树的插入操作是将要插入的节点与当前节点的值进行比较,如果小于当前节点的值,则继续在左子树中插入;如果大于当前节点的值,则继续在右子树中插入。当找到一个空节点时,就将要插入的节点作为该空节点的子节点。删除操作需要分为三种情况:删除叶子节点、删除只有一个子节点的节点和删除有两个子节点的节点。删除叶子节点很简单,只需要将其父节点的对应子节点置为空即可。删除只有一个子节点的节点,需要将其子节点替换为该节点的位置。删除有两个子节点的节点,则可以找到该节点的后继节点(即右子树中最小的节点),将其替换为该节点,然后删除后继节点。 5. 什么是衡二叉树衡二叉树是一种特殊的二叉树,它保证左右子树的高度差不超过1。这种衡可以确保二叉树的查找、插入和删除操作的时间复杂度都是O(logn)。常见的衡二叉树包括红黑树和AVL树。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值