溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

基于紅黑樹(shù)插入操作原理及java實(shí)現(xiàn)的示例分析

發(fā)布時(shí)間:2021-08-05 15:19:43 來(lái)源:億速云 閱讀:111 作者:小新 欄目:編程語(yǔ)言

這篇文章主要介紹基于紅黑樹(shù)插入操作原理及java實(shí)現(xiàn)的示例分析,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!

紅黑樹(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ù)的操作如果不畫圖很容易搞糊涂,下面通過(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)

基于紅黑樹(shù)插入操作原理及java實(shí)現(xiàn)的示例分析

 基于紅黑樹(shù)插入操作原理及java實(shí)現(xiàn)的示例分析

基于紅黑樹(shù)插入操作原理及java實(shí)現(xiàn)的示例分析

基于紅黑樹(shù)插入操作原理及java實(shí)現(xià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有必要畫個(gè)圖示:

基于紅黑樹(shù)插入操作原理及java實(shí)現(xiàn)的示例分析

以上是“基于紅黑樹(shù)插入操作原理及java實(shí)現(xiàn)的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI