计算机中的树(2)
总目录传送门:
目录
从二叉查找树到二叉平衡树
二叉查找树(Binary Search Tree):
二叉搜索树就是在二叉树的基础上,固定了数据存入的顺序,我们固定左边子树小于根节点,右边子树大于根节点,存入的时候排好顺序,那么我们搜索的速度就会加快很多了。而且不仅搜索,还支持快速插入和删除数据
二叉搜索树有以下特点:
-
若任意节点的左⼦树不空,则左⼦树上所有结点的值均⼩于它的根结点的值;
-
若任意节点的右⼦树不空,则右⼦树上所有结点的值均⼤于它的根结点的值;
-
任意节点的左、右⼦树也分别为⼆叉查找树
我们从root节点:27来看,27的左子树都是小于27的,右子树都是大于27的,他的左子树和右子树也都是二叉查找树。我们就说这个树是一个二叉查找树。
这样的好处是什么呢?这就解决了一个搜索的无序性问题,我们要搜索一个数,只需要对当前节点的大小与目标值进行判断,首先判断是否相等,然后判断大于就递归查询右子树,小于就遍历查询左子树,大大的减少了搜索的O。
但是二叉查找树会不会存在一种特殊情况呢?当二叉查找树处于链状结构的时候,他的搜索又会回到遍历链表的情况:
如果我们对一个二叉搜索树进行了操作,导致其成为上图的链状结构的时候,我们会发现,这个树满足二叉树的所有定义,但是他的O还是达到了O(n),也就是遍历链表。因此,在二叉查找树的基础上,又出现了AVL树,红黑树,它们两个都是基于二叉查找树,只是在二叉查找树的基础上又对其做了限制.
平衡二叉树(ALV Tree):
AVL树是带有平衡条件的二叉查找树,一般是用平衡因子差值判断是否平衡并通过旋转来实现平衡,左右子树树高不超过1。不管我们是执行插入还是删除操作只要左右子树树高超过了1,我们就要通过旋转来保持平衡。所以这种数据结构一般用于删除增加较少,查询较多的情况完全平衡的状态下,最好的情况是 O(logn)。
平衡的定义是说从空链接到根节点距离相等
平衡二叉树中一个重要的概念就是左旋和右旋:
右旋的基本实现就是,当成为一个连续左链(左子树树高超过了1)的情况下,用自己的左子节点代替自己的位置,然后自己变成右子节点:
假设我们有一个树,节点是2-3:
这时我们需要插入一个新节点1:
此时1-3的高超过了1,所以右旋:用2代替3的位置,3变成2的右子节点:
左旋也是相同的道理,我们在上图中插入4和5:
1节点和节点3的高度相差超过了1,所以我们用4代替3的位置,然后3变成4的左子节点:
那么我再继续插入6会出现什么情况呢:
很明显节点2的左子树右子树的高度相差超过了1,所以左旋(注意2-4-3),用4代替2的位置,3变成2的右子节点:
继续插入7:
很明显需要左旋来达到平衡:
这时候如果我们先插入10,再插入9会变成什么样呢:也就是先查大的,再插相对小的
这个结构和我们之前看到的是不同的,所以这种情况我们需要进行两次旋转:
我们首先主要这三个节点,这种降低高度很明显需要变成下图:
所以我们需要先右旋用9代替10的位置,然后10变成9的右子节点:
然后再左旋,用9代替7的位置,7变成9的左子节点,就得到了上面我们想要的形态:
这时候整体图变成了:
结合上图总结一下规律:
插入方式 | 描述 | 旋转方式 |
---|---|---|
LL | 在a的左子树根节点的左子树上插入节点而破坏平衡 | 右旋转 |
RR | 在a的右子树根节点的右子树上插入节点而破坏平衡 | 左旋转 |
LR | 在a的左子树根节点的右子树上插入节点而破坏平衡 | 先左旋后右旋 |
RL | 在a的右子树根节点的左子树上插入节点而破坏平衡 | 先右旋后左旋 |
这就是平衡二叉树的基本性质与平衡方法。但是我们也可以明显的发现,AVL树为了实现完全的平衡,他的旋转操作很多,所以增加和删除的性能损耗就会很大。所以红黑树作为新的数据结构,就是用来处理插入和删除相对较多的情况下的使用。