社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
二叉查找树是常用的一种二叉树,他支持快速插入,删除,查找操作,各个操作的时间复杂度跟树的高度成正比,理想情况下,时间复杂度是O(logn)
理解红黑树之前,必须先了解另一种树,叫2-3树,红黑树背后的逻辑就是它
2-节点
即普通节点:包含一个元素,两条子链接。3-节点
则是扩充版,包含2个元素和三条链接:两个元素A、B,左边的链接指向小于A的节点,中间的链接指向介于A、B值之间的节点,右边的链接指向大于B的节点。要判断一个键是否在树中,我们先将它和根结点中的键比较。如果它和其中的任何一个相等,查找命中。否则我们就根据比较的结果找到指向相应区间的链接,并在其指向的子树中递归地继续查找。如果这是个空链接,查找未命中。
要在2-3树
中插入一个新结点,我们可以和二叉查找树一样先进行一次未命中的查找,然后把新结点挂在树的底部。但这样的话树无法保持完美平衡性。我们使用2-3树的主要原因就在于它能够在插入之后继续保持平衡。
如果未命中的查找结束于一个2-节点
,我们只要把这个2-节点
替换为一个3-节点
,将要插入的键保存在其中即可。如果未命中的查找结束于一个3-结点,事情就要麻烦一些.
情况一:只有一个3-结点的树,向其插入一个新键
将3-节点
扩充为一个4-节点
,即包含三个元素的节点,然后将其分解,变成一棵二叉树
情况二:向一个父节点为2-节点
的3-节点
中插入新键
此时一样将 3-节点
扩充为4-节点
,但不为中键创建一个新的节点,而是分解4-节点
,将中键移动到父节点
3-节点
的3-节点
中插入新键4-节点
并分解它,然后将它的中键插入它的父节点中。但父节点也是一个3-节点
,因此再用这个中键构造一个新的临时4-节点
,然后在这个节点上进行相同的变换,即分解这个父结点并将它的中键插入到它的父结点中去。就这样,一直向上不断分解临时的4-节点
并将中键插入更高的父节点,直至遇到一个2-节点
,然后根据情况二处理当你了解了这些后,便可以看红黑树。
log2n
, 所以加入红色节点之后,最长路径不会超过 2log2n
,即,红黑树的高度近似2log2n
上面这些没看懂也没关系,通俗易懂话来讲:红黑树就是用红链接表示 3-节点
的 2-3树
红黑树中,所有的节点都是标准的2-节点
,为了体现出3-节点
,这里将3-节点
的两个元素用左斜红色的链接连接起来,即连接了两个2-节点
来表示一个3-节点
。这里红色节点标记就代表指向其的链接是红链接,黑色标记的节点就是普通的节点。固有红黑树的另一种定义是满足下列条件的二叉查找树:
红链接均为左链接。
没有任何一个结点同时和两条红链接相连。(这样会出现4-节点)
该树是完美黑色平衡的,即任意空链接到根结点的路径上的黑链接数量相同。
这里其实就是将 3-节点
中的两个元素用二叉树形式表现出来
①:Treap,Splay Tree,绝大部分情况下,它们操作的效率都很高,但是也无法避免极端情况下时间复杂度的退化。尽管这种情况出现概率不大,但是对于单次操作时间非常敏感的场景来讲,它们不适用。
②:AVL树是一种高度平衡的二叉树,所以查找的效率非常高,但是,有利有弊,AVL树为了维持这种高度平衡,要付出更多代价,每次插入,删除都要做调整,就比较复杂,耗时。所以有频繁的插入,删除操作的数据集合,使用AVL树的代价就有点高了。
③:红黑树只是做到了近似平衡,并不是严格的平衡,所以维护平衡的成本上,要比AVL树低。
所以,红黑树的插入,删除,查找各种操作性能都比较稳定。对于工程应用来说,结果状态可控可预期。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!