红黑树与2-3树

红黑树(也是一棵二分搜索树)
1.每个节点或者是红色的,或者是黑色的
2.根节点是黑色的
3.每一个叶子节点(最后的空节点)是黑色的
4.如果一个节点是红色的,那么他的孩子节点都是黑色的
5.从任意一个节点到叶子节点,经过的黑色节点是一样的
6.红黑树是保持“黑平衡”得二叉树
7.红黑树红色节点都是向左倾斜的
红黑树与2-3树等价
1.2-3树满足二分搜索树的基本性质
2.节点可以存放一个或者俩个元素
3.每个节点有2个或者3个孩子(有俩孩子,叫做二节点,有三个孩子,叫做三节点)
2-3树添加元素
4.2-3树是一颗绝对平衡的树(也就是二三节点融合)在我们前面的二分搜索树中我们知道,左子树的元素值一定小于根节点,右子树的值大于根节点,因此我们往2-3树中添加元素也要遵循这一点,假如他是一个2节点,则添加时直接编程三节点,假如是三节点,则就变成了四节点,四节点又会变成三个二节点,依次类推,保持绝对平衡,添加节点一定不会添加到空位置,从根节点直到叶子节点
1.如果插入三节点为叶子节点,父亲节点为2节点
插入的元素与根节点进行融合形成一个3节点
2.如果插入三节点为叶子结点,父亲节点为3节点
插入元素与父亲节点进行融合形成一个4节点,将4节点拆成3个二节点,然后再继续向上融合,以此类推
公共代码如下

	private static final boolean RED = true;
	private static final boolean BLACK = false;
	private class Node {
		public K key;
		public V value;
		public Node left, right;
		public boolean color;
		public Node(K key, V value) {
			this.key = key;
			this.value = value;
			left = null;
			right = null;
			color = RED; 
		}
	}

	private Node root;
	private int size;

	public RBTree() {
		root = null;
		size = 0;
	}

	public int getSize() {
		return size;
	}

	public boolean isEmpty() {
		return size == 0;
	}

颜色的反转
将黑色变为红色,红色变为黑色,与2-3树的4节点类似
具体的实现代码如下

//颜色翻转
	private void filpColor(Node node) {
		node.color = RED;
		node.left.color = BLACK;
		node.right.color = BLACK;
	}

右旋转
将孩子节点的右子树连接到父亲节点的左子树,然后将父亲节点连接到孩子节点的右子树,将父亲节点变为红色,孩子节点变为黑色(颜色反转)具体的实现代码如下

	//红黑树的右旋转
	private Node rightRotate(Node node) {
		Node x = node.left;
		//右旋转
		node.left = x.right;
		x.right = node;

		x.color = node.color;
		node.color = RED;

		return x;
	}

左旋转
将孩子节点的左子树连接到父亲节点的右子树,然后将父亲节点连接到孩子节点的左子树,将父亲节点变为红色,孩子节点变为黑色(颜色反转)具体的实现代码如下

	//红黑树的左旋转
	private Node leftRotate(Node node) {
		
		Node x = node.right;
		//左旋转
		node.right  =x.left;
		x.left = node;
		
		x.color = node.color;
		node.color = RED;
		
		return x;
	}

2-3树的三节点就相当于红黑树中父亲孩子节点,三节点中较大的数作为父亲节点,较小的数作为孩子节点
红黑树添加新元素(永远添加红色节点)
与2-3添加新的元素类似,如果树为空,直接添加即可,然后把红色变为黑色(颜色翻转),如果不是的话直接类似2-3树的添加元素,将根节点变为黑色,孩子节点为红色,如果添加元素是在左子树,直接添加,如果在右子树,我们需要进行左旋转,同时节点互换,如果在2-3树节点中间添加元素,那么就需要进行对孩子左旋转,在进行对父亲节点右旋转,最后进行颜色翻转。
1.右孩子为红色节点,左孩子不是红色节点。(进行左旋转,颜色翻转)
2.左孩子为红色节点,左孩子的左孩子为红色节点(进行右旋转,颜色翻转)
3.左孩子和右孩子都为红色节点,(直接进行颜色翻转)
具体的实现代码如下:

// 向以node为根的红黑树中插入元素(key,value),递归算法
	// 返回插入新节点后红黑树的根
	private Node add(Node node, K key, V value) {
		if (node == null) {
			size++;
			return new Node(key, value);//默认插入为红色节点
		}

		if (key.compareTo(node.key) < 0) {
			node.left = add(node.left, key, value);
		} else if (key.compareTo(node.key) > 0) {
			node.right = add(node.right, key, value);
		} else {
			node.value = value;
		}
		//红黑树的维护
		if(isRed(node.right) && !isRed(node.left)) {
			node = leftRotate(node);
		}
		if(isRed(node.left) && isRed(node.left.left)) {
			node = rightRotate(node);
		}
		if(isRed(node.left) && isRed(node.right)) {
			flipColor(node);
		}
		return node;
	}

红黑树的性能总结
1.对于完全随机的数据,普通的二分搜索树很好用
缺点:极端情况退化成链表(或者高度不平衡)
2.对于查询较多的使用情况,AVL树很好用!
3.红黑树牺牲了平衡性,统计性能更优(综合增删改查所有操作)
以上就是我对红黑树与2-3树的理解,不喜勿喷,谢谢!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值