日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

红黑树的原理_红黑树插入算法实现原理分析

發(fā)布時(shí)間:2025/3/19 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 红黑树的原理_红黑树插入算法实现原理分析 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

-

引言
紅黑樹是在實(shí)際工程中被廣泛應(yīng)用的一種數(shù)據(jù)結(jié)構(gòu),比如Linux中的線程調(diào)度就是使用的紅黑樹來管理進(jìn)程控制塊,而Nginx中也是使用紅黑樹來管理的timer,Java中的TreeMap和TreeSet也是基于紅黑樹來實(shí)現(xiàn)的。紅黑樹相比普通二叉查找樹的一個(gè)優(yōu)勢(shì)就是它的樹高為~lgN,所以不管是查找/插入/刪除操作它均能保證能夠在對(duì)數(shù)時(shí)間之內(nèi)完成。本文我們就先來了解一下紅黑樹插入算法的實(shí)現(xiàn)。
紅黑樹的定義
紅黑樹可以定義成含有紅黑鏈接并且滿足下列條件的二叉查找樹:

  • 紅鏈接均為左鏈接。
  • 沒有任何一個(gè)節(jié)點(diǎn)同時(shí)和兩條紅鏈接相連。
  • 任意空鏈接到根節(jié)點(diǎn)的路徑上的黑鏈接數(shù)目相同。p.s: 我們將指向一棵空樹的鏈接稱為空鏈接。
  • 比如下圖就是一棵典型的紅黑樹,如果之前了解過2-3樹的話(不了解也沒有關(guān)系,我們下面的內(nèi)容并不會(huì)涉及到2-3樹),可以發(fā)現(xiàn)如果將紅黑樹中的紅色結(jié)點(diǎn)畫平,實(shí)際上它就是2-3樹的一種變形,不過相比2-3樹,紅黑樹的查找操作要簡(jiǎn)單的多,但它同時(shí)也結(jié)合了2-3樹中高效的插入操作,所以說紅黑樹其實(shí)是普通的二叉查找樹和2-3樹兩種數(shù)據(jù)結(jié)構(gòu)優(yōu)點(diǎn)的結(jié)合。

    紅黑樹的定義 在實(shí)現(xiàn)紅黑樹之前我們先來定義一棵紅黑樹: public class RedBlackLiteBST<Key extends Comparable<Key>, Value> {private static final boolean RED = true;private static final boolean BLACK = false;private Node root; // root of the BSTprivate int n; // number of key-value pairs in BST// BST helper node data typeprivate class Node {private Key key; // keyprivate Value val; // associated dataprivate Node left, right; // links to left and right subtreesprivate boolean color; // color of parent linkpublic Node(Key key, Value val, boolean color) {this.key = key;this.val = val;this.color = color;}} }在上面的代碼中,我們將鏈接的顏色保存在表示該結(jié)點(diǎn)的Node對(duì)象中的color變量中。如果指向它的鏈接是紅色的,那么該變量為true,黑色則為false,我們規(guī)定空鏈接都為黑色。如下圖所示,指向結(jié)點(diǎn)C的鏈接是紅色,那么我們就將h.left.color設(shè)置為紅色,指向結(jié)點(diǎn)J的鏈接是黑色的,我們就將h.right.color設(shè)置為黑色。


    紅黑樹的顏色表示
    紅黑樹的幾種基本操作
    紅黑樹相比普通的二叉查找樹的一個(gè)重要優(yōu)勢(shì)就是插入的高效性,但是正因?yàn)槿绱思t黑樹的插入操作的算法實(shí)現(xiàn)相比普通的二叉樹要復(fù)雜一些。在正式實(shí)現(xiàn)插入算法之前,我們有必要先了解一下對(duì)于紅黑樹的幾種基本操作。
    左旋轉(zhuǎn)
    如下圖所示,現(xiàn)在我們有一條紅色的右鏈接,現(xiàn)在我們想要將這條紅色右鏈接轉(zhuǎn)換為左鏈接,這個(gè)操作過程就叫做左旋轉(zhuǎn):


    左旋轉(zhuǎn)之前
    我們要做的就是在保持紅黑樹平衡性的同時(shí),將上圖的結(jié)構(gòu)變?yōu)橄旅孢@樣:


    左旋轉(zhuǎn)之后
    仔細(xì)觀察可以發(fā)現(xiàn),我們要實(shí)現(xiàn)的其實(shí)就是將紅色鏈接關(guān)聯(lián)的兩個(gè)節(jié)點(diǎn)中由較小的節(jié)點(diǎn)E作為根節(jié)點(diǎn)轉(zhuǎn)換成由較大的節(jié)點(diǎn)S作為根節(jié)點(diǎn)。同時(shí)在這個(gè)過程中為了保持二叉樹中左子樹都要小于根節(jié)點(diǎn),右子樹都要大于根節(jié)點(diǎn),所以如果S節(jié)點(diǎn)還存在的話左鏈接我們還需要將它變成E節(jié)點(diǎn)的右鏈接。具體的實(shí)現(xiàn)代碼如下:private Node rotateLeft(Node h) {assert (h != null) && isRed(h.right);Node x = h.right;h.right = x.left;x.left = h;x.color = h.color;h.color = RED;return x;}右旋轉(zhuǎn)
    右旋轉(zhuǎn)的實(shí)現(xiàn)和左旋轉(zhuǎn)的實(shí)現(xiàn)是類似的,就是將一個(gè)紅色左鏈接轉(zhuǎn)換成一個(gè)紅色右鏈接:


    右旋轉(zhuǎn)之前
    與左旋轉(zhuǎn)的時(shí)候相反,我們要做的其實(shí)就是紅色鏈接關(guān)聯(lián)的兩個(gè)節(jié)點(diǎn)中較大的節(jié)點(diǎn)S作為根節(jié)點(diǎn)轉(zhuǎn)換成由較小的節(jié)點(diǎn)E作為根節(jié)點(diǎn):


    右旋轉(zhuǎn)之后
    所以轉(zhuǎn)換成具體的代碼,我們只需要將left和right相互轉(zhuǎn)換就行了:private Node rotateRight(Node h) {assert (h != null) && isRed(h.left);Node x = h.left;h.left = x.right;x.right = h;x.color = h.color;h.color = RED;return x;}顏色轉(zhuǎn)換
    上面我們提到紅黑樹的一個(gè)重要特性就是紅鏈接均為做左鏈接,所以對(duì)于下面這種情形,如果一個(gè)結(jié)點(diǎn)的兩個(gè)子結(jié)點(diǎn)均為紅色鏈接,我們就將子結(jié)點(diǎn)的顏色全部由紅色轉(zhuǎn)換成黑色,同時(shí)將父結(jié)點(diǎn)的顏色由黑變紅。


    顏色轉(zhuǎn)換之前


    顏色轉(zhuǎn)換之后
    具體的實(shí)現(xiàn)代碼非常簡(jiǎn)單:private void flipColors(Node h) {assert !isRed(h) && isRed(h.left) && isRed(h.right);h.color = RED;h.left.color = BLACK;h.right.color = BLACK;}插入操作的實(shí)現(xiàn)
    上面說了這么多,其實(shí)都是為接下來的插入操作做的預(yù)熱。接下來結(jié)合下圖,我們來分析紅黑樹插入操作過程我們會(huì)遇到的三種情形:

  • 插入的新結(jié)點(diǎn)c大于樹中現(xiàn)存的兩個(gè)鍵,所以我們要將它連接到b結(jié)點(diǎn)的右鏈接。因?yàn)檫@個(gè)時(shí)候b的兩條鏈接都是紅鏈接,所以我們要進(jìn)行flipColors。接下來可以發(fā)現(xiàn),我們下面的兩種情況都會(huì)轉(zhuǎn)換成這種情形。
  • 插入的新結(jié)點(diǎn)a要比樹中現(xiàn)存的兩個(gè)鍵都要小,所以我們先將它連接到結(jié)點(diǎn)b的左鏈接,前面我們提到紅黑樹的一個(gè)特性就是沒有任何一個(gè)節(jié)點(diǎn)可以同時(shí)和兩個(gè)紅色鏈接相連,而現(xiàn)在b結(jié)點(diǎn)卻違背了這一原則,所以我們要進(jìn)行右旋轉(zhuǎn)操作,接下來情形1是一模一樣的了。
  • 插入的新結(jié)點(diǎn)b在樹中現(xiàn)存的兩個(gè)鍵之間,所以我們先將它連接到結(jié)點(diǎn)a的右鏈接,前面我們提到紅黑樹中紅色鏈接都是左鏈接,所以我們首先要進(jìn)行左旋轉(zhuǎn)操作,接下來就和情形2一模一樣了。

  • 插入操作的3種情形
    插入操作的具體實(shí)現(xiàn)代碼如下,下面的代碼直到// fix-up any right-leaning right之前我們做的都是為了找到合適的插入位置,而之后的3個(gè)if語句實(shí)際上就是對(duì)上圖中情形3的一種總結(jié)。public void put(Key key, Value val) {root = insert(root, key, val);root.color = BLACK;// assert check(); // Check integrity of red-black tree data structure.}private Node insert(Node h, Key key, Value val) {if (h == null) {n++;return new Node(key, val, RED);}int cmp = key.compareTo(h.key);if (cmp < 0) h.left = insert(h.left, key, val);else if (cmp > 0) h.right = insert(h.right, key, val);else h.val = val;// fix-up any right-leaning linksif (isRed(h.right) && !isRed(h.left)) h = rotateLeft(h);if (isRed(h.left) && isRed(h.left.left)) h = rotateRight(h);if (isRed(h.left) && isRed(h.right)) flipColors(h);return h;}isRed的實(shí)現(xiàn)非常簡(jiǎn)單,我就不解釋了:// is node x red (and non-null) ?private boolean isRed(Node x) {if (x == null) return false;return x.color == RED;}

    總結(jié)

    以上是生活随笔為你收集整理的红黑树的原理_红黑树插入算法实现原理分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。