红黑树的原理_红黑树插入算法实现原理分析
-
引言
紅黑樹是在實(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)。
紅黑樹的定義
紅黑樹可以定義成含有紅黑鏈接并且滿足下列條件的二叉查找樹:
比如下圖就是一棵典型的紅黑樹,如果之前了解過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ì)遇到的三種情形:
插入操作的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)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 转换时间格式24小时_国内(上海)原油期
- 下一篇: 雷达成像技术_毫米波立体成像雷达技术研究