红黑树
一、红黑树
1.定义:红黑树时含有红黑节点并满足下列条件的二叉查找树
1)红色节点均为左节点
2)不能有两个连续的红节点
3)该树为完美黑色平衡的,即任意空连接到根节点的路径相同
2.红黑树的平衡化
1)左旋:当前节点的左子节点为黑色,右子节点为红色时。
* 左旋的过程:(1)让x节点的左子节点变为h的右子节点。
(2)x的右子节点变为h
(3)让h的color属性变为x的color属性
(4)h节点变为红色
2)右旋 :当某个节点的左子节点为红色,左子节点的左子节点也为红色,则需要右旋
右旋过程:(1)让x节点的右子节点做为h节点的左子节点
(2)让h作为x的右子节点
(3)让x的colcor变成h的colcor属性值
(4)让h的color为Red
3)颜色反转
当一个节点的左子节点和右子节点都为红色,此时需要反转,只需把两个子节点变为黑色,而把父节点变为红色即可。
注意:在每次插入时的节点都为红色节点,根节点默认为黑色
红黑树的设计:
public class RedBlackTree<Key extends Comparable<Key>, Value> { //根节点 private Node root; //个数 private int N; //黑色节点 private static final boolean RED=true; //红色节点 private static final boolean BLACK=false; /** * 节点类 */ public class Node{ //存储键 public Key key; //存储值 public Value value; //左子节点 public Node left; //右子节点 public Node right; //节点的颜色 public boolean color; public Node(Key key, Value value, Node left, Node right, boolean color) { this.key = key; this.value = value; this.left = left; this.right = right; this.color = color; } } /** * 获取数中个数 */ public int size(){ return N; } /** * 判断当前节点是否为红色 */ public boolean isRed(Node x){ if (x==null){ return false; } return x.color==RED; } /** * 左旋转 */ private Node rotateLeft(Node h){ //获取h右子节点表示为x Node x=h.right; //将x左节点设为h的右节点 h.right=x.left; //将x的左节点设为h x.left=h; //把x的color变为h的color属性 x.color=h.color; //h变为红色 h.color=RED; return x; } /** * 右旋 */ private Node rotateRight(Node h){ //获取h的左子节点设为x Node x =h.left; //让x的右子节点变为h的左子节点 h.left=x.right; //让h做为x的右子节点 x.right=h; //让x的color等于h的color属性 x.color=h.color; //让h的color为红色 h.color=RED; return x; } /** * 颜色反转 */ private void flipColors(Node h){ //让父节点变为红色 h.color=RED; //让左右子节点都变为黑色 h.left.color=BLACK; h.right.color=BLACK; } /** * 在整个树上完成插入操作 */ public void put(Key key,Value value){ root= put(root,key,value); //让根节点的颜色总是黑色 root.color=BLACK; } /** * 在指定数中插入操作,并返回添加元素新树 */ private Node put(Node h,Key key,Value value){ //判断h是否为空,为空返回一个红色节点 if (h==null){ N++; return new Node(key,value,null,null,RED); } //不为空时,判断h节点的key值和key的大小 int cmp = key.compareTo(h.key); if (cmp>0){ //继续往右 h.right=put(h.right,key,value); }else if (cmp<0){ //继续往左 h.left=put(h.left,key,value); }else { //替换 h.value=value; } //进行左旋,h的左子节点为黑色,右子节点为红色 if (isRed(h.right) && !isRed(h.left)){ h=rotateLeft(h); } //进行右旋,h的左子节点和左子节点的左子节点都为红色 if (isRed(h.left) && isRed(h.left.left)){ h=rotateRight(h); } //颜色反转,h的左右子节点都为红色 if (isRed(h.left) && isRed(h.right)){ flipColors(h); } return h; } //根据key,从树中找到值 public Value get(Key key){ return get(root,key); } //从指定的树中,查找key作对应的值 public Value get (Node x,Key key){ if (x == null){ return null; } int cmp = key.compareTo(x.key); if (cmp>0){ return get(x.right,key); }else if (cmp<0){ return get(x.left,key); }else { return x.value; } } }