vlambda博客
学习文章列表

数据结构(一)、二叉树(BT),二叉查找树(BST),平衡二叉树(AVL树)

二叉树(BT)

简介

二叉树(Binary Tree)是数据结构中一种重要的数据结构,也是树表家族最为基础的结构。二叉树是指树中节点的度不大于2的有序树,它是一种最简单且最重要的树。

概念

  • :节点拥有的子树数目;

  • 深度:树中节点的最大层次数称为树的深度或高度;

  • 子节点:节点子树的根节点为该节点的孩子节点;

  • 父节点:子节点定义中的节点就是相对的父节点;

  • 兄弟节点:同一个父节点的子节点;

定义

二叉树的递归定义为:二叉树是一棵空树(称为空二叉树),或者是一棵由一个根节点和两棵互不相交的,分别称作根的左子树和右子树组成的非空树;左子树和右子树又同样都是二叉树。

性质

  1. 二叉树的第i层上至多有数据结构(一)、二叉树(BT),二叉查找树(BST),平衡二叉树(AVL树)(i≥1)个节点

  2. 深度为h的二叉树中至多含有数据结构(一)、二叉树(BT),二叉查找树(BST),平衡二叉树(AVL树)个节点

  3. 若在任意一棵二叉树中,有n个叶子节点,有数据结构(一)、二叉树(BT),二叉查找树(BST),平衡二叉树(AVL树)个度为2的节点,则必有数据结构(一)、二叉树(BT),二叉查找树(BST),平衡二叉树(AVL树)

  4. 具有n个节点的完全二叉树深为数据结构(一)、二叉树(BT),二叉查找树(BST),平衡二叉树(AVL树)(其中x表示不大于n的最大整数)

  5. 若对一棵有n个节点的完全二叉树进行顺序编号(1≤i≤n),那么,对于编号为i(i≥1)的节点:

    1. 当i=1时,该节点为根,它无双亲节点

    2. 当i>1时,该节点的双亲节点的编号为i/2

    3. 若2i≤n,则有编号为2的左孩子,否则没有左孩子

    4. 若2+1≤n,则有编号为2i+1的右孩子,否则没有右孩子

遍历

四种基本的遍历思想:

  • 前序遍历:根节点 ---> 左子树 ---> 右子树

  • 中序遍历:左子树---> 根节点 ---> 右子树

  • 后序遍历:左子树 ---> 右子树 ---> 根节点

  • 层次遍历:按照树的层次自上而下的遍历二叉树

 

二叉查找树(BST)


简介

二叉查找树【二叉排序树(Binary Sort Tree),二叉搜索树(Binary Search Tree)】 是数据结构中的一类。二叉查找树作为一种经典的数据结构,它既有链表的快速插入与删除操作的特点,又有数组快速查找的优势;所以应用十分广泛,例如在文件系统和数据库系统一般会采用这种数据结构进行高效率的排序与检索操作。

性质

  1. 若左子树不空,则左子树上所有节点的值均小于它的根节点的值;

  2. 若右子树不空,则右子树上所有节点的值均大于或等于它的根节点的值;

  3. 左、右子树也分别为二叉排序树;

  4. 没有键值相等的节点;

数据结构(一)、二叉树(BT),二叉查找树(BST),平衡二叉树(AVL树)

对二叉查找树进行中序遍历,即可得到有序的数列。

如上图:[2,4,5,7,8,9,12,13,16,20]

算法

二叉查找树的插入过程如下:

  1. 若当前的二叉查找树为空,则插入的元素为根节点;

  2. 若插入的元素值小于根节点值,则将元素插入到左子树中;

  3. 若插入的元素值不小于根节点值,则将元素插入到右子树中;

二叉查找树的深度决定了二叉查找树的查找效率。

二叉查找树的删除,分三种情况进行处理:

  1. 叶子节点:直接删除,不影响原树;

  2. 仅仅有左或右子树的节点:节点删除后,将它的左子树或右子树整个移动到删除节点的位置就可以,子承父业;

  3. 既有左又有右子树的节点:找到须要删除的节点p的直接前驱或者直接后继s,用s来替换节点p,然后再删除节点s;

 

二叉平衡树(AVL树)

简介

对于一般的二叉搜索树(Binary Search Tree),其期望高度(即为一棵平衡树时)为数据结构(一)、二叉树(BT),二叉查找树(BST),平衡二叉树(AVL树),其各操作的时间复杂数据结构(一)、二叉树(BT),二叉查找树(BST),平衡二叉树(AVL树)

同时也由此而决定。但在某些极端的情况下(如在插入的序列为有序插入时),二叉搜索树将退化成链或者近似链,此时,其操作的时间复杂度将退化成线性的,即O(n)。我们可以通过随机化建立二叉搜索树来尽量的避免这种情况,但是在进行了多次的操作之后,由于在删除时,我们总是选择将待删除节点的后继代替它本身,这样就会造成总是右边的节点数目减少,以至于树向左偏沉。这同时也会造成树的平衡性受到破坏,提高它的操作的时间复杂度。于是就有了平衡二叉树。

平衡二叉树的前提是一棵二叉排序树,刚才提到二叉排序树的查找性能受树的形状影响较大,所以需要对二叉排序树进行平衡处理,常见的方法有AVL、红黑树、Treap等。

数据结构(一)、二叉树(BT),二叉查找树(BST),平衡二叉树(AVL树)

定义

AVL树是最先出现的自平衡二叉查找树,在AVL中任何节点的两个儿子子树的高度最大差别为1,所以它也被称为高度平衡树,n个节点的AVL树最大深度约数据结构(一)、二叉树(BT),二叉查找树(BST),平衡二叉树(AVL树)。查找、插入和删除在平均和最坏情况下都是O(logn)。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。这个方案很好的解决了二叉查找树退化成链表的问题,把插入,查找,删除的时间复杂度最好情况和最坏情况都维持在O(logN)。但是频繁旋转会使插入和删除牺牲掉O(logN)左右的时间,不过相对二叉查找树来说,时间上稳定了很多。

平衡因子:平衡二叉树上的节点左子树的深度减去右子树的深度的值成为该节点的平衡因子,平衡因子取值只能为0,-1,1;

最小不平衡子树:距离插入节点最近的,且以平衡因子的绝对值大于1的节点为根节点的子树;

性质

  1. 非叶子节点最多拥有两个子节点;

  2. 非叶子节值大于左边子节点、小于右边子节点;

  3. 树的左右两边的层级数相差不会大于1;

  4. 没有值相等重复的节点;

平衡过程:旋转

  • RR型旋转:插入节点在最小不平衡子树的左子树的左子树。即当最小不平衡子树根节点的平衡因子大于1时,该子树右旋。

  • LL型旋转:插入节点在最小不平衡子树的右子树的右子树。LL型旋转当最小不平衡子树根节点的平衡因子小于1时,该子树左旋。

  • 插入节点后,最小不平衡子树的平衡因子与它的子树的平衡因子符号相反时,需要对它的子树先进行一次旋转,再对它本身反向旋转一次才能完成平衡操作。

    • LR型旋转:插入节点在最小不平衡子树的左子树的右子树。

    • RL型旋转:插入节点在最小不平衡子树的右子树的左子树。

例: 

LL左旋和RR右旋类似,下面演示LL左旋的情景:

  1. 新增25节点之后,AVL平衡二叉树打破了平衡条件 性质3;

  2. 9节点的左树深度为2,右树深度为4,此时需要对9节点做左旋平衡操作;

  3. LL左旋之后,12升级为根节点,由于节点只能有两个子节点,因此10节点转到9节点的右树下;

  4. LL左旋完成后,AVL树回归平衡状态,成功插入25节点;

LR旋转和RL旋转类似,下面演示LR旋转的情景:

  1. 新增11节点之后,AVL平衡二叉树打破了平衡条件 性质3;

  2. 12节点的左树深度为4,右树深度为2,此时需要对12节点做左旋平衡操作;

  3. 左树左旋之后,7升级为左树的根节点,由于节点只能有两个子节点,因此6节点转到5节点的右树下;

  4. 此时12节点的左树仍然是4深度,右树深度仍然是2,

  5. 对树整体右旋,7升级为树的根节点,由于节点只能有两个子节点,因此8节点转到12节点的右树下;

  6. 右旋整树之后,平衡二叉树回归平衡状态,成功插入11节点;

 

希望本文对你有帮助,请点个赞鼓励一下作者吧~ 谢谢!