咱们回忆一下AVL树,它在插入和删除节点时,总要保证任意节点左右子树的高度差不超过1。正是由于有这样的限制,插入一个节点和删除一个节点都有可能调整多个节点的不平衡状态。频繁的左旋转和右旋转操做必定会影响整个AVL树的性能,除非是平衡与不平衡变化不多的状况下,不然AVL树所带来的搜索性能提高不足以弥补平衡树所带来的性能损耗。算法
那有没有绝对平衡的一种树呢?没有高度差也不会有平衡因子,没有平衡因子就不会调整旋转操做。2-3树正是一种绝对平衡的树,任意节点到它全部的叶子节点的深度都是相等的。segmentfault
2-3树的数字表明一个节点有2到3个子树。它也知足二分搜索树的基本性质,但它不属于二分搜索树。ide
一颗2-3树或为一颗空树,或有如下节点组成:性能
2-节点,含有一个元素和两个子树(左右子树),左子树全部元素的值均小于它父节点,右子树全部元素的值均大于它父节点;动画
3-节点,还有两个元素和三个子树(左中右子树),左子树全部元素的值均小于它父节点,中子树全部元素的值都位于父节点两个元素之间,右子树全部元素的值均大于它父节点;spa
子树也是空树、2-节点或者3-节点;3d
没有元素相等的节点。视频
2-3树的查找相似二分搜索树的查找,根据元素的大小来决定查找的方向。要判断一个元素是否存在,咱们先将待查找元素和根节点比较,若是它和其中任意一个相等,那查找命中;不然根据比较的结果来选择查找的方向。对象
插入元素首先进行查找命中,若查找命中则不予插入此元素,若是须要支持重复的元素则将这个元素对象添加一个属性count。若查找未命中,则在叶子节点中插入这个元素。blog
空树的插入很简单,建立一个节点便可。若是不是空树,插入的状况分为4种:
1.向2-节点中插入元素;
2.向一颗只含有一个3-节点的树中插入元素;
3.向一个父节点为2-节点的3-节点中插入元素;
4.向一个父节点为3-节点的3-节点中插入元素。
若是未命中查找结束于2-节点,直接将2-节点替换为3-节点,并将待插入元素添加到其中。
若是命中查找结束于3-节点,先临时将其成为4-节点,把待插入元素添加到其中,而后将4-节点转化为3个2-节点,中间的节点成为左右节点的父节点。若是以前临时4-节点有父节点,就会变成向一个父节点为2-节点的3-节点中插入元素,中间节点与父节点为2-节点的合并。
插入元素后一直向上分解临时的4-节点,直到遇到2-节点的父节点变成3-节点再也不分解
。若是达到树根节点仍是4-节点,则进行分解根节点,此时树高+1(只有分解根节点才会增长树高),下面动画2-3树插入会出这个例子。
算法4红黑树删除最小键这一小结里没有特别详细地介绍,但给到了沿着左连接向下进行变换的三种状况:
若是左子节点不是2-节点,完成;
若是左子节点是2-节点,而兄弟节点不是2-节点,将兄弟节点的最小元素移到父节点,父节点的最小元素移到左子节点;
若是左子节点是2-节点,而兄弟节点是2-节点,则左子结点、父节点中最小的元素和兄弟结点合并成4-结点。
咱们注意到在叶子节点不是2-节点的时候,删除一个元素是很简单的,并且删除时不考虑自平衡处理。若是删除一个2-节点会留下一个空节点,破坏了2-3树的绝对平衡。因此,为了保证不会删除一个2-节点,能够设定最左边或者最右边进行向下变换节点。这里设置沿最左边的连接,进行向下变换的三种状况正是如上图中,左子节点的父节点除了根节点都会变换成3-节点或4-节点。
删除任意元素须要进行命中查找。若是查找未命中则忽略之;若是查找命中则向二叉堆同样删除任意元素,将带删除元素右子树的最小元素替换到待删除元素上,而后对右子树进行删除最小元素。
动画视频地址
喜欢本文的朋友,欢迎关注公众号「算法无遗策」,收看更多精彩内容