NX_Java_03 2-3树、红黑树

脑中要构想出连贯的动画,一切都是以这个动画为基础的;然后给别人讲明白

2-3树,有助于理解红黑树

  • 理解:
    每个节点都可以存放一个元素或者两个元素
    存放一个元素的节点称为2-节点、存放两个元素的节点叫做3-节点
    每个节点有2个或者3个子节点的树称为2-3树,2-3树满足二叉搜索树的基本性质
    2-3树是一个 绝对平衡 的树(平衡因子等于0)
    添加节点的时候,是 不可以向null节点插入数据
    在这里插入图片描述

  • 插入节点的不同情景
    如果插入2-节点;——》2节点变3节点
    如果插入3-节点;——》先形成一个4节点,然后把4节点进行分裂
    等等……

  • 2-树和红黑树的等价性
    2-3树里面的2节点上面的元素相当于黑色节点;如果是3节点,我们这里研究的是左倾红黑树,讲3节点左面的元素作为红色,右面的作为黑色。
    在这里插入图片描述

  • 对比2-3树,引出红黑树的相关特点:
    在这里插入图片描述
    关键点:
    以左倾红黑树为基础(红色节点向左倾斜);
    根节点必须是黑色;
    每个叶子节点必须是黑的;
    新插入的节点必须是红的

  • 红黑树添加元素的三种情况:

  1. 新插入的节点在父节点的右边——》左旋+颜色交换
  2. 3个节点,父节点是黑色,两个子节点是红色的(此时为4节点,不满足2-3树的特征)——》颜色翻转,父节点为红,子节点为黑
  3. node.color=BLACK,node.left.color=RED,node.left.left.color=RED(此时不满足2-3树特征)——》右旋+颜色翻转
  4. node.color=BLACK,node.left.color=RED,node.left.right.color=RED——》L+R+CP
  • 手撕红黑树
/**
 * 老师的代码
 * @param <E>
 */
public class RBT<E extends Comparable<E>> {

	private static final boolean RED = true;
	private static final boolean BLACK = false;

	public Node root;
	private int size;

	public int size() {
		return size;
	}

	//添加节点,递归
	public void addEle(E e) {
		root = addEle(root, e);
		root.color = BLACK;
	}

	/**
	 * 将元素E添加到以node为根的那个树上并且将新树的根返回
	 *
	 * @param node
	 * @param e
	 * @return
	 */
	private Node addEle(Node node, E e) {
		if (node == null) {
			size++;
			return new Node(e);
		}
		if (e.compareTo(node.e) < 0) {
			node.left = addEle(node.left, e);
		} else {
			node.right = addEle(node.right, e);
		}

		//左旋的操作
		if (isRed(node.right) && !isRed(node.left)) {
			node = leftRotate(node);
		}

		//右旋
		if (isRed(node.left) && isRed(node.left.left)) {
			node = rightRotate(node);
		}

		//颜色翻转
		if (isRed(node.right) && isRed(node.left)) {
			flipColors(node);
		}

		return node;
	}


	//     node                   x
	//    /   \     右旋转       /  \
	//   x    T2   ------->   y   node
	//  / \                       /  \
	// y  T1                     T1  T2
	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 void flipColors(Node node) {
		node.color = RED;
		node.left.color = BLACK;
		node.right.color = BLACK;
	}

	//   node                     x
	//  /   \     左旋转         /  \
	// T1   x   --------->   node   T3
	//     / \              /   \
	//    T2 T3            T1   T2
	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;
	}

	private boolean isRed(Node node) {
		if (node == null) return BLACK;
		return node.color;
	}


	private class Node {
		public E e;
		public Node left;
		public Node right;
		public boolean color;

		public Node(E e) {
			this.e = e;
			this.left = null;
			this.right = null;
			this.color = RED;
		}

		@Override
		public String toString() {
			return "Node{" +
					"e=" + e +
					", color=" + color +
					'}';
		}
	}


	/**
	 * 层次遍历树
	 */
	public void levelOrder() {
		if (root == null) {
			return;
		}
		Queue<Node> queue = new LinkedList();
		queue.add(root);
		while (!queue.isEmpty()) {
			Node curNode = queue.remove();
			System.out.println(curNode);
			if (curNode.left != null) {
				queue.add(curNode.left);
			}
			if (curNode.right != null) {
				queue.add(curNode.right);
			}
		}
	}
}

  • 三种树的应用场景
    对于完全随机的数据,BST不会出现一侧偏斜的情况,极端情况下会退化成链表或者非常不平衡树
    对于查询较多的业务场景,AVL是最佳的选择
    RBT的综合性能更优
    HashMap在Java8后引入了红黑树,TreeMap、TreeSet的底层也是红黑树
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值