基于紅黑樹(shù)插入操作原理及java實(shí)現(xiàn)方法(分享)
紅黑樹(shù)是一種二叉平衡查找樹(shù),每個(gè)結(jié)點(diǎn)上有一個(gè)存儲(chǔ)位來(lái)表示結(jié)點(diǎn)的顏色,可以是RED或BLACK。
紅黑樹(shù)具有以下性質(zhì):
(1) 每個(gè)結(jié)點(diǎn)是紅色或是黑色
(2) 根結(jié)點(diǎn)是黑色的
(3) 如果一個(gè)結(jié)點(diǎn)是紅色的,則它的兩個(gè)兒子都是黑色的
(4) 對(duì)于每個(gè)結(jié)點(diǎn),從該結(jié)點(diǎn)到其子孫結(jié)點(diǎn)的所有路徑上包含相同數(shù)目的黑結(jié)點(diǎn)
通過(guò)紅黑樹(shù)的性質(zhì),可以保證所有基于紅黑樹(shù)的實(shí)現(xiàn)都能保證操作的運(yùn)行時(shí)間為對(duì)數(shù)級(jí)別(范圍查找除外。它所需的額外時(shí)間和返回的鍵的數(shù)量成正比)。
Java的TreeMap就是通過(guò)紅黑樹(shù)實(shí)現(xiàn)的。
紅黑樹(shù)的操作如果不畫(huà)圖很容易搞糊涂,下面通過(guò)圖示來(lái)說(shuō)明紅黑樹(shù)的插入操作。
插入一個(gè)紅色的節(jié)點(diǎn)到紅黑樹(shù)中之后,會(huì)有6種情況:圖示中N表示插入的節(jié)點(diǎn),P表示父節(jié)點(diǎn),U表示叔叔節(jié)點(diǎn),G表示祖父節(jié)點(diǎn),X表示當(dāng)前操作節(jié)點(diǎn)




代碼如下:
public class RedBlackBST<Key extends Comparable<Key>, Value> {
private Node root;
private static final boolean RED = true;
private static final boolean BLACK = false;
private class Node{
private Key key; //鍵
private Value val; //值
private Node left, right, parent; //左右子樹(shù)和父節(jié)點(diǎn)
private boolean color; //由其父節(jié)點(diǎn)指向它的鏈接的顏色
public Node(Key key, Value val,Node parent, boolean color){
this.key = key;
this.val = val;
this.color = color;
}
}
public Value get(Key key){
Node x = root;
while(x!=null){
int cmp = key.compareTo(x.key);
if(cmp < 0 ) x = x.left;
else if(cmp > 0) x = x.right;
else return x.val;
}
return null;
}
public void put(Key key, Value val){
if(root==null) { //如果是根節(jié)點(diǎn),就將節(jié)點(diǎn)新建為黑色
root = new Node(key,val,null,BLACK);
return;
}
//尋找合適的插入位置
Node parent = null;
Node cur = root;
while(cur!=null) {
parent = cur;
if(key.compareTo(cur.key)>0) cur=cur.right;
else cur = cur.left;
}
Node n = new Node(key,val,parent,RED); //普通的新建節(jié)點(diǎn)為紅色
//將新節(jié)點(diǎn)插入parent下
if(key.compareTo(parent.key) > 0) parent.right = n;
else parent.left = n;
//插入新節(jié)點(diǎn)后要調(diào)整樹(shù)中部分節(jié)點(diǎn)的顏色和屬性來(lái)保證紅黑樹(shù)的特征不被破壞
fixAfterInsertion(n);
}
private Node parentOf(Node x) {
return (x==null ? null : x.parent);
}
private boolean colorOf(Node x) {
return (x==null ? BLACK : x.color);
}
private Node leftOf(Node x) {
return (x==null ? null : x.left);
}
private Node rightOf(Node x) {
return(x==null ? null : x.right);
}
private void setColor(Node x, boolean color) {
if(x!=null)
x.color = color;
}
private void fixAfterInsertion(Node x) {
while(x!=null && colorOf(parentOf(x)) == RED) {
Node grandPa = parentOf(parentOf(x));
Node parent = parentOf(x);
if(parent == leftOf(grandPa)) {//case 1 || case2 || case3
Node uncle = rightOf(grandPa);
if(colorOf(uncle) == RED) {//case1, uncle is red
setColor(parent,BLACK); //父節(jié)點(diǎn)置黑
setColor(uncle, BLACK); //叔叔節(jié)點(diǎn)置黑
setColor(grandPa,RED); //祖父節(jié)點(diǎn)置紅
x = grandPa; //因?yàn)樽娓腹?jié)點(diǎn)由黑轉(zhuǎn)紅,故要重新調(diào)整父節(jié)點(diǎn)及其祖先的紅黑屬性
}else {//case2 || case3,uncle is black
if(x==rightOf(parent)) { //case2
x = parent;
rotateLeft(x);
}
//case3
setColor(parent,BLACK);
setColor(grandPa, RED);
rotateRight(grandPa);
}
}else {//case4 || case 5 || case6
Node uncle = leftOf(grandPa);
if(colorOf(uncle) == RED) { //case4 || case5 || case6
setColor(parent,BLACK);
setColor(uncle, BLACK);
setColor(grandPa,RED);
x = grandPa;
}else{ //case5 || case6, uncle is black
if(x==leftOf(parent)) { //case5
x = parent;
rotateRight(x);
}
//case6
setColor(parent,BLACK);
setColor(grandPa, RED);
rotateLeft(grandPa);
}
}
}
}
private void rotateLeft(Node x) {
if(x==null) return;
Node y = x.right;
x.right = y.left;
if(y.left!=null)
y.left.parent = x;
y.left = x;
y.parent = x.parent;
if(x.parent == null) {
root = y;
}
else if(x.parent.left == x) {
x.parent.left = y;
}else {
x.parent.right = y;
}
x.parent = y;
}
private void rotateRight(Node x) {
if(x==null) return;
Node y = x.left;
x.left = y.right;
if(y.right != null)
y.right.parent = x;
y.right = x;
y.parent = x.parent;
if(x.parent == null) {
root = y;
}else if(x.parent.left==x) {
x.parent.left = y;
}else {
x.parent.right=y;
}
x.parent = y;
}
}
上面的rotateLeft和rotateRight有必要畫(huà)個(gè)圖示:

以上這篇基于紅黑樹(shù)插入操作原理及java實(shí)現(xiàn)方法(分享)就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- Java實(shí)現(xiàn)紅黑樹(shù)(平衡二叉樹(shù))的詳細(xì)過(guò)程
- 利用Java實(shí)現(xiàn)紅黑樹(shù)
- Java紅黑樹(shù)的數(shù)據(jù)結(jié)構(gòu)與算法解析
- 通過(guò)java.util.TreeMap源碼加強(qiáng)紅黑樹(shù)的理解
- java算法實(shí)現(xiàn)紅黑樹(shù)完整代碼示例
- java中treemap和treeset實(shí)現(xiàn)紅黑樹(shù)
- Java數(shù)據(jù)結(jié)構(gòu)之紅黑樹(shù)的真正理解
- 圖解紅黑樹(shù)及Java進(jìn)行紅黑二叉樹(shù)遍歷的方法
- Java 數(shù)據(jù)結(jié)構(gòu)與算法系列精講之紅黑樹(shù)
相關(guān)文章
Mybatis攔截器實(shí)現(xiàn)數(shù)據(jù)權(quán)限的示例代碼
在我們?nèi)粘i_(kāi)發(fā)過(guò)程中,通常會(huì)涉及到數(shù)據(jù)權(quán)限問(wèn)題,本文主要介紹了Mybatis攔截器實(shí)現(xiàn)數(shù)據(jù)權(quán)限的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
Lucene實(shí)現(xiàn)多種高級(jí)搜索形式
這篇文章主要介紹了Lucene實(shí)現(xiàn)多種高級(jí)搜索形式的相關(guān)資料,需要的朋友可以參考下2017-04-04
SpringMVC @RequestMapping注解作用詳解
通過(guò)@RequestMapping注解可以定義不同的處理器映射規(guī)則,下面這篇文章主要給大家介紹了關(guān)于SpringMVC中@RequestMapping注解用法的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-01-01

