二叉树:树的每个节点最多只能有两个子节点
二叉搜索树:
参考图片

查找:搜索值小于当前节点搜左子树,大于当前节点搜右子树,等于表示搜到 插入:类似查找,直到左子树或右子树为空时认为找到了插入位置
遍历:
参考图片

最值:
删除:
二分查找:数组有序情况下,对半查,参考下图

缺点:必须是有序的,而且是数组,不可以是链表
可以看出,二叉搜索树和二分查找有一定的相似度
二叉搜索树存在一种极端情况,这种情况下会退化为一个有序链表

由于退化成链表后搜索效率过低,需要设计一种树,在插入元素的时候自动调整两边平衡,保持高查询性能。这里暂不分析AVL树,本节重点是红黑树
AVL树特点:

虽然AVL树解决了二叉搜索树的极端情况,但是由于高度差限制过于严格,导致效率过低
于是引出了红黑树的概念
红黑树具有以下的性质,如果满足那么这棵树就是趋于平衡状态的:



红黑树的插入等操作会涉及到多种情况,暂不分析,直接上代码,在代码中分析
xxxxxxxxxx// 树节点static class RBNode<K extends Comparable<K>, V> { private RBNode parent; private RBNode left; private RBNode right; private boolean color;
private K key; private V value;
// 构造 get set // ......}
xxxxxxxxxx/*** 左旋* p p* | |* x y* / \ ---> / \* lx y x ry* / \ / \* ly ry lx ly** (1) x.right=y.left* (2) y.left.parent=x* (3) y.parent=x.parent* (4) x.parent=y** @param x 左旋节点*/private void leftRotate(RBNode x) { RBNode y = x.right; // (1) x.right = y.left; // (2) if (y.left != null) { y.left.parent = x; } // (3) if (x.parent != null) { y.parent = x.parent; if (x == x.parent.left) { x.parent.left = y; } else { x.parent.right = y; } } else { // root this.root = y; } // (4) x.parent = y; y.left = x;}
xxxxxxxxxx/*** 右旋* p p* | |* y x* / \ ---> / \* x ry lx y* / \ / \* lx ly ly ry** (1) y.left=x.right* (2) x.right.parent=y* (3) x.parent=y.parent* (4) y.parent=x** @param y 右旋节点*/private void rightRotate(RBNode y) { RBNode x = y.left; // (1) y.left = x.right; // (2) if (x.right != null) { x.right.parent = y; } // (3) if (y.parent != null) { x.parent = y.parent; if (y == y.parent.left) { y.parent.left = x; } else { y.parent.right = x; } } else { // root this.root = x; this.root.parent = null; } // (4) y.parent = x; x.right = y;}
xxxxxxxxxx/*** 对外的插入* @param key key* @param value value*/public void insert(K key, V value) { RBNode node = new RBNode(); node.setKey(key); node.setValue(value); // 新节点一定是红色 node.setColor(RED); insert(node);}
/*** 插入实现* @param node 插入节点*/private void insert(RBNode node) { RBNode parent = null; RBNode x = this.root;
while (x != null) { parent = x; // cmp>0:node.key>x.key->遍历右子树 // cmp=0:node.key=x.key->replace // cmp<0:node.key<x.key->遍历左子树 int cmp = node.key.compareTo(x.key); if (cmp > 0) { x = x.right; } else if (cmp == 0) { x.setValue(node.getValue()); return; } else { x = x.left; } } node.parent = parent; if (parent != null) { // cmp>0:node.key>parent.key->node在parent右子节点 // cmp<0:node.key<parent.key->node在parent左子节点 int cmp = node.key.compareTo(parent.key); if (cmp > 0) { parent.right = node; } else { parent.left = node; } } else { this.root = node; }
// 恢复平衡 insertFixup(node);}
xxxxxxxxxxprivate void insertFixup(RBNode node) { this.root.setColor(BLACK); // 父节点 RBNode parent = parentOf(node); // 父节点的父节点 RBNode gparent = parentOf(parent); // 父节点为黑色直接平衡 // 父节点为红色应分多种情况 if (parent != null && isRed(parent)) { // 父节点的父节点的另一个子节点(叔叔) RBNode uncle = null; // 父节点是爷节点左节点 if (parent == gparent.left) { uncle = gparent.right; /** * | | * gp(B) gp(R) * / \ ---> / \ * p(R) u(R) p(B) u(B) * / / * n(R) n(R) */ if (uncle != null && isRed(uncle)) { // 重新染色后下一轮处理 setBlack(parent); setBlack(uncle); setRed(gparent); insertFixup(gparent); return; } if (uncle == null || isBlack(uncle)) { /** * | | * gp(B) p(B) * / \ ---> / \ * p(R) u(B) n(R) gp(R) * / \ * n(R) u(B) */ if (node == parent.left) { setBlack(parent); setRed(gparent); // 右旋 rightRotate(gparent); return; } /** * | | * gp(B) gp(B) * / \ ---> / \ ---> 上一步 * p(R) u(B) n(R) u(B) * \ / * n(R) p(R) */ if (node == parent.right) { leftRotate(parent); insertFixup(parent); // 右旋 return; } } } else { // 父节点是右节点 uncle = gparent.left; /** * | | * gp(B) gp(R) * / \ ---> / \ * u(R) p(R) u(B) p(B) * / / * n(R) n(R) */ if (uncle != null && isRed(uncle)) { // 重新染色后下一轮处理 setBlack(parent); setBlack(uncle); setRed(gparent); insertFixup(gparent); return; } // 不存在叔节点 if (uncle == null || isBlack(uncle)) { /** * | | * gp(B) p(B) * / \ ---> / \ * u(B) p(R) gp(R) n(R) * \ / * n(R) u(R) */ if (node == parent.right) { setBlack(parent); setRed(gparent); leftRotate(gparent); return; } /** * | | * gp(B) gp(B) * / \ ---> / \ ---> 上一步 * u(B) p(R) u(B) n(R) * / \ * n(R) p(R) */ if (node == parent.left) { rightRotate(parent); insertFixup(parent); return; } } } }}