前言:其实这些树原理都很容易说出来,重点在于去实现,以及各个问题的亲为。
我暂时不会直接在本文中给出源代码,而是重点说原理和模拟实现误区。
二叉搜索树:
规则:
1.可以是一个空树。
2.如果左子树不为空,则左子树上所有节点都小于根节点的值。
3.如果右子树不为空,则右子树上所有节点都大于根节点的值。
4.他的左右子树也是搜索二叉树。
5.不会有重复值。
模拟实现突出点:
删除:
如以上搜索二叉树图示,删除节点分三种情况,根节点,有一个根节点的节点,有两个根节点的节点。
删除根节点好说,直接删了就行,重点在于后面两种,先说只有一个的,直接把他的孩子给他的父节点就行。就像”留守儿童“。
两个节点呢,就需要有人接待他的位置,那哪些节点可以胜任呢,首先看他可以的条件,比左边都大,比右边都小,好,到这里结果已经显而易见了,就是左边最大节点和右边最小节点,所以二者皆可。
至于插入和查找,直接按照规则做就可以。
这个树当然会出现以下的状况,今天下五子棋的时候也摆出过此阵,我愿叫他苦茶子阵。
这就是规则不全带来的后果,以下两种就会有增加更多的改进之处。
AVL树:
规则:
1.包含上纵规则(部分)
2.左右子树都是AVL树
3.左右子树的高度差(平衡因子)的绝对值不超过1
这里注意一点就是AVL树不一定有平衡因子,他只是一种实现的方式,有很多实现的方式。
平衡因子就是右子树节点个数减去左子树节点个数,不算子节点的另支,左减右,右减左都可以,具体可以单搜下这个。
查找和删除还是那样,插入的话只需要注意平衡因子和规则了(默认带平衡因子的版本),那么就涉及到这里的坑了。
模拟实现突出点:
旋转:
当插入后,高度的变化破环了规则,那么就需要要有所措施。
先把旋转这个东西画出来,这个就是右单旋,相而也有左单旋,用于调节高度,当然这只是示例。
现在文字说明下这个,第一个左节点做头节点,他的右节点变成前头节点的左节点,头节点变成他左节点的右节点。
当然只有左单旋和右单旋不够用,所以还有左右双旋,代码就不举例了,这里的重点便是这个了(个人认为)。
红黑树:
规则:
1.每个节点不是黑色就是红色。
2.没有一条路径是其他路径的两倍。
3.根节点是黑色。
4.如果一个节点是红色,那他的两个子节点必须是红色。
5.每条路径上的黑色节点是相同的。
模拟实现突出点:
插入:
这里先说下,默认插入节点是红色,因为既然插入一个节点给他颜色的话,就意味着必须违反规则四或者五,相对比下选择插入节点为红色。
情况一
有叔节点并且叔节点为红色:
把新插入节点叫cur,此外还用的到的三个节点,然后进行下图的操作。
把父节点和叔节点变成黑色,祖父节点变成红色,此时祖父节点和他的父节点冲突,把祖父节点当作cur,继续进行上述操作。
最后再把祖父节点变黑就好了。
这样就算插入完成了。
情况二
有叔节点并且叔节点为黑色
比如以上的情况,左下的节点有两个红。
把他的父节点和叔节点全都换成黑色。
再把祖父节点做成插入节点类推,最后头节点还是黑色。
情况三
没有叔节点
首先把父节点变黑。
然后进行左单旋,并且把祖父节点变红。
这样就完事了。