24张图,九大数据结构安排得明明白白( 二 )


树的数据存储在结点中 , 每个结点有零个或者多个子结点 。没有父结点的结点在最顶端 , 成为根节点;没有非根结点有且只有一个父节点;每个非根节点又可以分为多个不相交的子树 。
这意味着树是具备层次关系的 , 父子关系清晰 , 家庭血缘关系明朗;这也是树与图之间最主要的区别 。

24张图,九大数据结构安排得明明白白

文章插图
 
别看树好像很高级 , 其实可看作是链表的高配版 。树的实现就是对链表的指针域进行了扩充 , 增加了多个地址指向子结点 。同时将“链表”竖起来 , 从而凸显了结点之间的层次关系 , 更便于分析和理解 。
树可以衍生出许多的结构 , 若将指针域设置为双指针 , 那么即可形成最常见的二叉树 , 即每个结点最多有两个子树的树结构 。二叉树根据结点的排列和数量还可进一度划分为完全二叉树、满二叉树、平衡二叉树、红黑树等 。
24张图,九大数据结构安排得明明白白

文章插图
 
完全二叉树:除了最后一层结点 , 其它层的结点数都达到了最大值;同时最后一层的结点都是按照从左到右依次排布 。
满二叉树:除了最后一层 , 其它层的结点都有两个子结点 。
平衡二叉树平衡二叉树又被称为AVL树 , 它是一棵二叉排序树 , 且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1 , 并且左右两个子树都是一棵平衡二叉树 。
二叉排序树:是一棵空树 , 或者:若它的左子树不空 , 则左子树上所有结点的值均小于它的根结点的值;若它的右子树不空 , 则右子树上所有结点的值均大于它的根结点的值;它的左、右子树也分别为二叉排序树 。
树的高度:结点层次的最大值
平衡因子:左子树高度 - 右子树高度
二叉排序树意味着二叉树中的数据是排好序的 , 顺序为左结点<根节点<右结点 , 这表明二叉排序树的中序遍历结果是有序的 。(还不懂二叉树四种遍历方式[前序遍历、中序遍历、后序遍历、层序遍历]的同学赶紧补习!)
24张图,九大数据结构安排得明明白白

文章插图
 
平衡二叉树的产生是为了解决二叉排序树在插入时发生线性排列的现象 。由于二叉排序树本身为有序 , 当插入一个有序程度十分高的序列时 , 生成的二叉排序树会持续在某个方向的字数上插入数据 , 导致最终的二叉排序树会退化为链表 , 从而使得二叉树的查询和插入效率恶化 。
24张图,九大数据结构安排得明明白白

文章插图
 
平衡二叉树的出现能够解决上述问题 , 但是在构造平衡二叉树时 , 却需要采用不同的调整方式 , 使得二叉树在插入数据后保持平衡 。主要的四种调整方式有LL(左旋)、RR(右旋)、LR(先左旋再右旋)、RL(先右旋再左旋) 。这里先给大家介绍下简单的单旋转操作 , 左旋和右旋 。LR和RL本质上只是LL和RR的组合 。
在插入一个结点后应该沿搜索路径将路径上的结点平衡因子进行修改 , 当平衡因子大于1时 , 就需要进行平衡化处理 。从发生不平衡的结点起 , 沿刚才回溯的路径取直接下两层的结点 , 如果这三个结点在一条直线上 , 则采用单旋转进行平衡化 , 如果这三个结点位于一条折线上 , 则采用双旋转进行平衡化 。
左旋:S为当前需要左旋的结点 , E为当前结点的父节点 。
24张图,九大数据结构安排得明明白白

文章插图
 
左旋的操作可以用一句话简单表示:将当前结点S的左孩子旋转为当前结点父结点E的右孩子 , 同时将父结点E旋转为当前结点S的左孩子 。可用动画表示:
24张图,九大数据结构安排得明明白白

文章插图
 
右旋:S为当前需要左旋的结点 , E为当前结点的父节点 。右单旋是左单旋的镜像旋转 。
24张图,九大数据结构安排得明明白白


推荐阅读