(1)若是插入是根節點,直接把節點塗爲黑色,把節點設置爲根節點html
(2)若是插入的節點的父節點是黑色,無需任何處理java
(3)須要修復的狀況ide
狀況1:當前節點的父節點爲紅色,叔叔節點爲紅色,解決辦法:(將當前節點的父節點和叔叔節點塗黑,祖父節點塗紅,把當前節點指向祖父節點,從新開始遞歸調整),根節點塗黑this
狀況2:當前節點的父節點爲紅色,叔叔節點爲null或者黑色(或者的狀況雖然在當前不存在,可是在狀況1的遞歸條件下是存在的),當前節點爲父節點的右孩子,解決辦法:須要先左旋,(左旋後,把父節點當成當前節點,當前節點的父節點塗黑,祖父節點塗紅,後右旋),根節點塗黑(父節點爲祖父左孩子的狀況)spa
狀況3:當前節點的父節點爲紅色,叔叔節點爲null或者黑色(或者的狀況雖然在當前不存在,可是在狀況1的遞歸條件下是存在的),當前節點爲父節點的左孩子,解決辦法:父節點塗黑,祖父節點塗紅,直接右旋,根節點塗黑(父節點爲祖父左孩子的狀況).net
(1)刪除紅色的葉子節點,直接刪除code
(2)刪除的紅色節點有左子樹或者右子樹的狀況,這種狀況不存在orm
(3)刪除黑色的葉子結點htm
狀況1:兄弟節點爲紅色,那父節點就必須爲黑色,解決方法:把兄弟節點和父節點顏色對調,而後左旋,就變成了狀況2,或者狀況3blog
狀況2:兄弟節點爲黑色節點,遠侄子節點爲紅色,解決辦法:把兄弟節點與父節點顏色對調,而後左旋,把侄子節點顏色變黑,刪除目的節點
狀況3:兄弟節點爲黑色節點,近侄子節點爲紅色,解決辦法:把近侄子節點和該侄子的父節點進行右旋,而後他兩顏色互換,而後就變成了狀況2
狀況4:兄弟節點爲黑色,侄子節點也爲黑色,這種狀況不存在(但,這種狀況在狀況6的遞歸狀況中是存在的,因此也得考慮)
狀況5:兄弟節點爲黑色,無侄子節點,父節點爲紅色,解決辦法:把父節點變成黑色,兄弟節點變成紅色,刪除目的節點
狀況6:兄弟節點爲黑色,無侄子節點,父節點爲黑色,解決辦法:把兄弟節點變成紅色,刪除目的節點,接着把當前節點指向父節點,而後按照父節點爲黑色葉子節點的狀況進行遞歸調整
(4)刪除的黑色節點有左子樹或者右子樹的狀況,固然這個時候它的左子樹或者右子樹節點只能是紅色不能是黑色,處理方法簡單:即用黑色節點的孩子替換黑色節點,並將替換後的節點染成黑色。
其中,insert一旋轉,向插入節點子樹的對立方向旋轉(以祖父爲中心)( 祖父節點和父節點顏色互換)
delete的二旋轉,兩次都是向刪除節點的同一方向旋轉(兩次都是以父親爲中心)(第一次旋轉:父節點和兄弟節點顏色互換)(第二次旋轉:父節點和兄弟節點顏色互換,侄子節點塗黑)
左旋或者右旋的三要素:
一、包含根節點的變動
二、除根節點外,包含三個點的操做
三、
package main; import java.util.LinkedList; import java.util.Queue; public class RBTree<T extends Comparable<T>> { private static final boolean RED = false; private static final boolean BLACK = true; private RBNode<T> root = null; public class RBNode<T>{ private T key; private boolean color; private RBNode<T> parent; private RBNode<T> left; private RBNode<T> right; public RBNode(T key) { this.key = key; this.color = RED; this.parent = null; this.left = null; this.right = null; } } public static void main(String[] args) { RBTree<Integer> rbree = new RBTree<>(); rbree.insert(1); rbree.insert(9); rbree.insert(5); rbree.insert(8); rbree.insert(2); rbree.insert(4); rbree.insert(7); rbree.insert(6); rbree.insert(3); rbree.insert(10); rbree.insert(11); rbree.insert(12); rbree.delete(5); rbree.delete(4); rbree.delete(10); rbree.delete(9); rbree.show(); } //紅黑樹的展現 public void show() { int h = height(this.root); Queue<RBNode<T>> queue = new LinkedList<>(); queue.add(this.root); RBNode<T> tempNode = null; for(int i=1;i<=h;++i) { for(int j=0;j<Math.pow(2, h-i)-1;++j) { System.out.print(" "); } for(int j=0;j<Math.pow(2, i-1);++j) { tempNode = queue.remove(); if(tempNode==null) { System.out.print("__"); System.out.print(":W"); queue.add(null); queue.add(null); }else { System.out.print(String.format("%2d", tempNode.key)); System.out.print(':'); System.out.print(tempNode.color?'B':'R'); queue.add(tempNode.left); queue.add(tempNode.right); } for(int k=0;k<Math.pow(2, h-i+1)-1;++k) { System.out.print(" "); } } System.out.println(); } } //紅黑樹的高度 public int height(RBNode<T> rootNode) { if(rootNode==null) { return 0; }else { return height(rootNode.left)>height(rootNode.right)?(height(rootNode.left)+1):(height(rootNode.right)+1); } } //節點的插入 public void insert(T key) { RBNode<T> newNode = new RBNode<>(key); RBNode<T> tempNode = this.root; RBNode<T> preNode = this.root; while(tempNode!=null) { preNode = tempNode; if(tempNode.key.compareTo(key)==0) { return; }else if(tempNode.key.compareTo(key)<0){ tempNode = tempNode.right; }else { tempNode = tempNode.left; } } if(preNode==null) { this.root = newNode; }else if(preNode.key.compareTo(key)<0) { preNode.right = newNode; newNode.parent = preNode; }else{ preNode.left = newNode; newNode.parent = preNode; } //節點插入後須要進行顏色和位置的調整 fixupInsert(newNode); } //節點插入的調整 public void fixupInsert(RBNode<T> newNode) { if(newNode.parent==null||newNode.parent.color == BLACK) { //父節點沒有或者父節點爲黑色時不作任何處理 }else { //父節點 RBNode<T> parentNode = newNode.parent; //祖父節點 RBNode<T> grandParentNode = parentNode.parent; //叔叔節點 RBNode<T> uncleNode = null; if(grandParentNode.left==parentNode) { uncleNode = grandParentNode.right; }else { uncleNode = grandParentNode.left; } //叔叔節點爲黑色(這裏的條件在遞歸中做用很大) if(uncleNode==null||uncleNode.color) { if(grandParentNode.left==parentNode&&parentNode.left==newNode) { parentNode.color = BLACK; grandParentNode.color = RED; rightRotate(grandParentNode); }else if(grandParentNode.left==parentNode&&parentNode.right==newNode){ leftRotate(parentNode); newNode.color = BLACK; grandParentNode.color = RED; rightRotate(grandParentNode); }else if(grandParentNode.right==parentNode&&parentNode.left==newNode){ rightRotate(parentNode); newNode.color = BLACK; grandParentNode.color = RED; leftRotate(grandParentNode); }else { parentNode.color = BLACK; grandParentNode.color = RED; leftRotate(grandParentNode); } }else {//叔叔節點位紅色 parentNode.color = BLACK; uncleNode.color = BLACK; grandParentNode.color = RED; fixupInsert(grandParentNode); } } this.root.color = BLACK;//根節點設爲黑色 } public void delete(T key) { RBNode<T> tempNode = this.root; RBNode<T> tempLeftNode = null; //尋找刪除的節點 while(tempNode!=null) { if(tempNode.key.compareTo(key)==0) { if(tempNode.left!=null&&tempNode.right!=null) { tempLeftNode = tempNode.left; while(tempLeftNode.right!=null) { tempLeftNode = tempLeftNode.right; } tempNode.key = tempLeftNode.key; tempNode = tempLeftNode; } break; }else if(tempNode.key.compareTo(key)<0) { tempNode = tempNode.right; }else { tempNode = tempNode.left; } } //須要刪除的節點爲tempNode if(tempNode!=null) { if(tempNode.left!=null) {//刪除節點有紅色的左孩子節點 tempNode.left.color = BLACK; if(tempNode.parent==null) { this.root = tempNode.left; tempNode.left.parent = null; }else { if(tempNode.parent.left==tempNode) { tempNode.parent.left = tempNode.left; tempNode.left.parent = tempNode.parent; }else { tempNode.parent.right = tempNode.left; tempNode.left.parent = tempNode.parent; } } }else if(tempNode.right!=null) {//刪除節點有紅色的右孩子節點 tempNode.right.color = BLACK; if(tempNode.parent==null) { this.root = tempNode.right; tempNode.right.parent = null; }else { if(tempNode.parent.left==tempNode) { tempNode.parent.left = tempNode.right; tempNode.right.parent = tempNode.parent; }else { tempNode.parent.right = tempNode.right; tempNode.right.parent = tempNode.parent; } } }else if(!tempNode.color){//刪除紅色葉子結點 if(tempNode.parent==null) { this.root = null; }else { if(tempNode.parent.left==tempNode) { tempNode.parent.left = null; }else { tempNode.parent.right = null; } } }else {//刪除黑色葉子結點 fixupDelete(tempNode);//先調整,後刪除 if(tempNode.parent==null) { this.root = null; }else { if(tempNode.parent.left==tempNode) { tempNode.parent.left = null; }else { tempNode.parent.right = null; } } } } } public void fixupDelete(RBNode<T> tempNode) { RBNode<T> parentNode = null; if(tempNode.parent==null) { return; }else { parentNode = tempNode.parent; } RBNode<T> uncleNode = null; if(parentNode.left==tempNode) { uncleNode = parentNode.right; }else { uncleNode = parentNode.left; } //刪除節點的兄弟節點爲紅色的狀況 if(parentNode.color==BLACK&&uncleNode.color==RED) { parentNode.color = RED; uncleNode.color = BLACK; if(parentNode.left==uncleNode) { rightRotate(parentNode); }else { leftRotate(parentNode); } if(parentNode.left==tempNode) { uncleNode = parentNode.right; }else { uncleNode = parentNode.left; } } //刪除節點的兄弟節點爲黑色的狀況 if(parentNode.right==uncleNode) { if(uncleNode.right!=null&&!uncleNode.right.color) {//遠侄子節點爲紅色 uncleNode.color = parentNode.color; parentNode.color = BLACK; uncleNode.right.color = BLACK; leftRotate(parentNode); }else if(uncleNode.left!=null&&!uncleNode.left.color){//近侄子節點爲紅色 uncleNode.left.color = parentNode.color; parentNode.color = BLACK; rightRotate(uncleNode); leftRotate(parentNode); }else if(parentNode.color) {//父節點爲黑色,兩個侄子節點爲null或者在低軌狀況下可能都爲黑色 uncleNode.color = RED; fixupDelete(parentNode); }else {//父節點爲紅色,兩個侄子節點爲null或者在低軌狀況下可能都爲黑色 uncleNode.color = RED; parentNode.color = BLACK; } }else { if(uncleNode.left!=null&&!uncleNode.left.color) {//遠侄子節點爲紅色 uncleNode.color = parentNode.color; parentNode.color = BLACK; uncleNode.left.color = BLACK; rightRotate(parentNode); }else if(uncleNode.right!=null&&!uncleNode.right.color) {//近侄子節點爲紅色 uncleNode.right.color = parentNode.color; parentNode.color= BLACK; leftRotate(uncleNode); rightRotate(parentNode); }else if(parentNode.color) {//父節點爲黑色,兩個侄子節點爲null或者在低軌狀況下可能都爲黑色 uncleNode.color = RED; fixupDelete(parentNode); }else {//父節點爲紅色,兩個侄子節點爲null或者在低軌狀況下可能都爲黑色 uncleNode.color = RED; parentNode.color = BLACK; } } this.root.color = BLACK; } //以參數節點爲中心進行左旋 public void leftRotate(RBNode<T> rotateNode) { RBNode<T> rightNode = rotateNode.right; //對承接節點的處理 if(rotateNode.parent==null) { rightNode.parent = null; this.root = rightNode; }else { rightNode.parent = rotateNode.parent; if(rotateNode.parent.left==rotateNode) { rotateNode.parent.left = rightNode; }else { rotateNode.parent.right = rightNode; } } //對支節點的處理 rotateNode.right = rightNode.left; if(rightNode.left!=null) { rightNode.left.parent = rotateNode; } //對當下節點的處理 rightNode.left = rotateNode; rotateNode.parent = rightNode; } //以參數節點爲中心進行右旋 public void rightRotate(RBNode<T> rotateNode) { RBNode<T> leftNode = rotateNode.left; //對承接節點的處理 if(rotateNode.parent==null) { leftNode.parent = null; this.root = leftNode; }else { leftNode.parent = rotateNode.parent; if(rotateNode.parent.left==rotateNode) { rotateNode.parent.left = leftNode; }else { rotateNode.parent.right = leftNode; } } //對支節點的處理 rotateNode.left = leftNode.right; if(leftNode.right!=null) { leftNode.right.parent = rotateNode; } //對當下節點的處理 leftNode.right = rotateNode; rotateNode.parent = leftNode; } }
紅黑樹的理解:https://blog.csdn.net/li2327234939/article/details/75628448
https://baijiahao.baidu.com/s?id=1623524026892185878&wfr=spider&for=pc
https://www.cnblogs.com/xuxinstyle/p/9556998.html
https://www.cnblogs.com/zedosu/p/6635034.html