红黑树通过以下规则维护平衡:
enum Color{ RED, BLACK } // 颜色枚举
static class Node {
int key; // 节点键值
Object value; // 存储数据
Node left, right; // 左右子节点
Node parent; // 父节点指针
Color color = Color.RED; // 默认红色
//判断是不是左孩子
boolean isLeftChild() {
return parent != null && parent.left==this;
}
//返回叔叔节点
Node uncle(){
if(parent==null||parent.parent==null) return null;
if(parent.isLeftChild()) {
return parent.parent.right;
}else {
return parent.parent.left;
}
}
//返回兄弟节点
Node subling(){
if(parent==null){
return null;
}
if(this.isLeftChild()){
return parent.right;
}else {
return parent.left;
}
}
}
平衡树结构的关键操作,分为左旋和右旋:
//右旋
private void rightRotate(Node node){
Node parent = node.parent;
Node node1 =node.left;
Node node2 =node.right;
if(node2!=null){
node2.parent = node;
}
node1.right=node;
node1.parent=node.parent;
node.left=node2;
node.parent=node1;
if(parent==null){
root = node1;
}
if(parent.left==node){
parent.left=node1;
}else {
parent.right=node1;
}
}
//左旋
private void leftRotate(Node node){
Node parent = node.parent;
Node node1=node.right;
Node node2=node1.left;
node1.left=node;
node.right=node2;
node.parent=node1;
if(node2!=null){
node2.parent=node;
}
if(parent==null){
root = node1;
}
if(parent.left==node){
parent.left=node1;
}else {
parent.right=node1;
}
}
boolean isRed(Node node){
return node!=null&& node.color==Color.RED;
}
boolean isBlack(Node node){
return !isRed(node);
}
插入后通过颜色调整维持平衡
void put(int key,Object value){
Node p=root;
Node parent = null;
while(p!=null){
parent=p;
if(p.keykey){
p=p.left;
}else {
p.value=value;
return;
}
}
Node inserted=new Node(key,value);
if(parent==null){
root = inserted;
}
if (parent.key>key){
parent.left=inserted;
inserted.parent=parent;
}else {
parent.right=inserted;
inserted.parent=parent;
}
fixRedRed(inserted);
}
当出现连续红节点时进行平衡调整:
void fixRedRed(Node node){
//插入节点为根节点,将根节点变成黑色。
if(node==root){
node.color=Color.BLACK;
return;
}
//插入节点的父亲节点为黑色,不必调整。
if(isBlack(node.parent)){
return;
}
//执行到这里,说明node既不是根节点,而且父亲节点是红色。
//红红相邻
Node parent=node.parent;
Node uncle=node.uncle();
Node grandparent=parent.parent;
//叔叔为红
if(isRed(uncle)){
node.parent.color=Color.BLACK;
uncle.color=Color.BLACK;
grandparent.color=Color.RED;
fixRedRed(grandparent);
return;
}
//执行到这里,就说明叔叔为黑色。
//LL
if(parent.isLeftChild()&& node.isLeftChild()){
parent.color=Color.BLACK;
grandparent.color=Color.RED;
rightRotate(grandparent);
//LR
}else if(parent.isLeftChild()&&!node.isLeftChild()){
leftRotate(parent);
node.color=Color.BLACK;
grandparent.color=Color.RED;
rightRotate(grandparent);
//RR
}else if(!parent.isLeftChild()&&!node.isLeftChild()){
parent.color=Color.BLACK;
grandparent.color=Color.RED;
leftRotate(grandparent);
//RL
}else {
rightRotate(parent);
node.color=Color.BLACK;
grandparent.color=Color.RED;
leftRotate(grandparent);
}
}
public void remove(int key) {
Node deleted = find(key);
if (deleted == null) return;
doRemove(deleted); // 执行实际删除
}
查找删除节点,以及替换节点
//查找删除节点
Node find(int key){
Node p=root;
while(p!=null){
if(p.key>key){
p=p.left;
}else if(p.key
删除主逻辑:
private void doRemove(Node deleted){
Node replace=findReplaced(deleted);
Node parent=deleted.parent;
if(replace==null){
if(deleted==root){
root=null;
}else {
if(isBlack(deleted)){
//删除节点时,可能会发生节点颜色失衡,违反第五条规则,调用修复方法:
fixBlackBlack(deleted);
}
if(deleted.isLeftChild()){
parent.left=null;
}else {
parent.right=null;
}
deleted.parent=null;
}
return;
}
//有一个孩子
if(deleted.left==null||deleted.right==null){
if(deleted==root){
root=replace;
replace.parent=null;
}else {
if(deleted.isLeftChild()){
parent.left=replace;
}else {
parent.right=replace;
}
replace.parent=parent;
if(isBlack(deleted)&&isBlack(replace)){
fixBlackBlack(replace);
}else {
replace.color=Color.BLACK;
}
}
deleted.left=deleted.right=null;
return;
}
//执行到这里,说明deleted有两个孩子。
int t=deleted.key;
deleted.key=replace.key;
replace.key=t;
Object v=deleted.value;
deleted.value=replace.value;
replace.value=v;
doRemove(replace);
}
双黑颜色调整:
private void fixBlackBlack(Node x){
if(x==root){
return;
}
Node parent=x.parent;
Node sibling=x.subling();
//当兄弟是红色
if(isRed(sibling)){
if(x.isLeftChild()){
leftRotate(parent);
}else {
rightRotate(parent);
}
parent.color=Color.RED;
sibling.color=Color.BLACK;
fixBlackBlack(x);
}
if(sibling != null){
//兄弟是黑色,两个侄子也是黑色
if(isBlack(sibling.left)&&isBlack(sibling.right)){
sibling.color=Color.RED;
if(isRed(parent)){
parent.color=Color.BLACK;
}else {
fixBlackBlack(parent);
}
//兄弟是黑色,至少有一个侄子是红色
}else{
if(sibling.isLeftChild()&&isRed(sibling.left)){
rightRotate(parent);
sibling.left.color=Color.BLACK;
sibling.color=sibling.parent.color;
parent.color=Color.BLACK;
}
else if(sibling.isLeftChild()&&isRed(sibling.right)){
sibling.right.color=parent.color;
leftRotate(sibling);
rightRotate(parent);
parent.color=Color.BLACK;
}
else if(!sibling.isLeftChild()&&isRed(sibling.left)){
sibling.left.color=parent.color;
rightRotate(parent);
leftRotate(parent);
}
else {
leftRotate(parent);
sibling.right.color=Color.BLACK;
sibling.color=sibling.parent.color;
parent.color=Color.BLACK;
}
}
}else{
fixBlackBlack(parent);
}
}