2020-12-14

2-3查找树(最简单B树)

多路查找树参考链接
对二叉树的一种改进:原有的二叉树是2-结点(一个键、两条链),而现在引入3-结点(两个键、三条链)。

定义: 最简单的B树,要求一棵2-3查找树要么为空,要么由以下结点组成:
(1)、2-结点的左链指向小于该结点的值;右链指向大于该结点的值。
(2)、3-结点左链指向小于该结点的值;中链指向位于该结点的两个键值之间的值;右链指向大于该结点的值。
在这里插入图片描述

查找操作(图片来于第四版算法)

在这里插入图片描述
易知,查找操作类似于二叉查找树的查找

插入操作(图片来于第四版算法)

(1)、最后插入位置是2-结点:直接将该结点转换为3-结点即可!
在这里插入图片描述
(2)、最后插入位置是3-结点:临时创建4-结点再分裂
在这里插入图片描述
(3)、向一个父结点是2-结点的3-结点中插入:
在这里插入图片描述
(4)、向一个父结点是3-结点的3-结点中插入:
在这里插入图片描述
(5)、分解根结点:
在这里插入图片描述

删除操作【复习二叉查找树的三种删除操作,图片来于大话数据结构】

(1)、删除非叶子结点:中序遍历下,用待删除节点的后继节点覆盖它即可。如下图的,要删除节点4,直接使用后继6覆盖掉4.
在这里插入图片描述
(2)、删除叶子节点:
a、叶子节点是3-结点:直接删除该值。如下图,删除9,因为它所在3-结点,因此直接删除即可。
在这里插入图片描述
b、叶子结点是2-结点:

b-1、叶子结点的父节点是2-结点,且兄弟结点是3-结点:将父节点移动到当前位置,再将兄弟节点中最接近当前位置的key移动到父节点中即可。
在这里插入图片描述
b-2、叶子结点的父节点是2-结点,兄弟结点也是2-结点:
在这里插入图片描述
b-3、叶子结点的父节点是3-结点:父节点分裂为2-结点
在这里插入图片描述
b-4、叶子结点位于满二叉树中:
在这里插入图片描述

2-3查找树的性质

1、高为h的2-3查找树所包含的节点数大于等于高度为h的满二叉树的节点数,即至少有2^h-1个节点。

2、任意空链接到根节点的路径长度是相等的。即2-3树的局部变换不会影响全局的有序性和平衡性。

3、二叉查找树是自顶向下生长;而2-3查找树是自底向上生长(B树都是自底向上生长的)

4、2-3查找树在插入后可以保证树的平衡状态,即使在最坏情况下是满二叉树,其高度也为logN。相较于普通的二叉查找树在最坏情况下退化为线性结构,确保了时间复杂度。

红黑树

红黑树(对应2-3-4树)和左倾红黑树(对应2-3树)

左倾红黑树既是二叉查找树,也是2-3树。2-3树的深度很小,平衡性好,效率高,但是其有两种不同的结点,实际代码实现比较复杂。而红黑树用红链接表示2-3树中另类的3-结点,统一了树中的结点类型,使代码实现简单化,又不破坏其高效性。

左倾红黑树定义

2-3树和红黑树
对2-3树进行编码,基本思想是利用标准的二叉查找树(完全由2-结点构成)和一些额外信息(替换3-结点)来表示2-3树。我们将树中链接分为两种:
红链接:将两个2-结点连接构成一个3-结点
黑链接:2-3树中普通链接
因此定义为:(左倾)红黑树是含有红黑链接并满足下列条件的二叉查找树:
1)、红链接均为左链接【左倾红黑树】;
2)、没有任何一个结点能同时和两条红链接相连;
3)、该树是完美黑色平衡的,即任意空链接到根结点路径上的黑链数量相同。
在这里插入图片描述

左倾红黑树平衡化

左旋(当某个结点的左子结点为黑色,右子结点为红色)

在这里插入图片描述

右旋(当某个结点的左子结点为红色,且左子结点的左子结点也为红色。注意右旋后反转颜色)

左倾红黑树插入操作

向2-结点插入(又分为插入值小于该2-结点、大于2-结点两种情况)

在这里插入图片描述

向3-结点插入(又分为插入值大于、小于、介于二者之间三种情况)

在这里插入图片描述

总结:操作时用2-3树思想实现,最后用左倾红黑树来表示即可
在这里插入图片描述

/*
* 左倾红黑树实现
*/
public class RedBlackTree {
	public Node root = null;// 根结点
	private int nodeCount;// 结点个数
	private static final boolean RED = true;
	private static final boolean BLACK = false;

	// 当前结点和父结点之间链接是否为红链接
	public boolean isRed(Node x) {
		if (x == null) {
			return false;
		}
		return x.color == RED;
	}

	// 树中元素个数
	public int size() {
		return nodeCount;
	}

	/* 左旋如下图形式:
	 *   h结点
	 *        x结点
	 *    h和x之间     大于x
	 */
	public Node rotateLeft(Node h) {
		Node x = h.right;// 获得当前结点的右子结点
		// 下面开始左旋
		h.right = x.left;
		x.left = h;
		x.color = h.color;
		h.color = RED;

		return x;// 返回左旋后的根
	}

	/* 右旋如下图形式:
	 * 			  h结点
	 *       x结点
	 *   小于x   x和h之间
	 */
	public Node rotateRight(Node h) {
		Node x = h.left;// 获得当前结点的左子结点
		// 下面开始右旋
		h.left = x.right;
		x.right = h;
		x.color = h.color;
		h.color = RED;

		return x;// 返回右旋后的根
	}

	/* 颜色反转(右旋之后)
	 * 		  结点h
	 *   hLeft  hRight【当前结点的左右孩子的color都为黑链接;并且当前结点的color为红】
	 */
	public void flipColors(Node h) {
		h.left.color = BLACK;
		h.right.color = BLACK;

		h.color = RED;
	}

	/*
	 * 向以node为根的BST插入结点
	 */
	public Node insert(Node node, int value) {

		if (node == null) {
			nodeCount++;
			return new Node(value, null, null, RED);
		}

		// 插入结点
		if (node.value > value) {
			node.left = insert(node.left, value);
		} else {
			node.right = insert(node.right, value);
		}

		// 插入结点后可能引起不平衡
		// 1、左旋
		if (isRed(node.right) && !isRed(node.left)) {
			node = rotateLeft(node);
		}
		// 2、右旋
		if (isRed(node.left) && isRed(node.left.left)) {
			node = rotateRight(node);
		}
		// 3、颜色反转
		if (isRed(node.left) && isRed(node.right)) {
			flipColors(node);
		}

		return node;// 返回插入后新BST的根结点
	}

	// 向红黑树中插入结点
	public void add(int value) {
		root = insert(root, value);
		root.color = BLACK;//根结点总是黑=
	}

	// 中序遍历红黑树
	public void search(Node node) {
		if (node == null) {
			return;
		}
		search(node.left);
		System.out.print(node.value + "  ");
		search(node.right);
	}

	public static void main(String[] args) {
		RedBlackTree tree = new RedBlackTree();

		tree.add(2);
		tree.add(3);
		tree.add(4);
		tree.add(5);
		tree.add(8);
		tree.add(7);

		System.out.println("红黑树的结点个数--->" + tree.size());
		System.out.println("红黑树的根结点的值--->" + tree.root.value);
		System.out.println("-------中序遍历红黑树------");
		tree.search(tree.root);
	}
}

2-3-4树和红黑树

2-3-4树只是在2-3树的基础上进行了扩展,也是一棵自平衡的多路查找树(B树),插入删除操作与2-3树类似。
在这里插入图片描述
对应的红黑树相比于左倾红黑树,其红链接也可以为右链接。注意:一棵2-3-4树可以对应多个红黑树;但是一个红黑树只能对应一个2-3-4树
在这里插入图片描述
PS:下面这种也对,但是上面更符合2-3树对应的红黑树的习惯。
在这里插入图片描述

红黑树和AVL树的比较

二者都是平衡树,都避免了二叉查找树退化为线性表。那么为什么还需要红黑树呢?直接使用AVL树不就行了吗?其实主要还是插入删除情况下,红黑树的效率更高。
AVL 树是高度平衡的,频繁的插入和删除,会引起频繁的reblance,导致效率下降。
红黑树不是高度平衡的,算是一种折中,插入最多两次旋转,删除最多三次旋转

2-3树等多路查找树和AVL树的比较

都是O(logN)级别查询效率,但是面对大数据量情况下,AVL树高度太大,相比下多路查找树高度会降低很多。因此多路查找树(B树)特别适合大数据量查找。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值