日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

大名鼎鼎的红黑树,你get了么?2-3树 绝对平衡 右旋转 左旋转 颜色反转

發(fā)布時(shí)間:2025/7/25 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 大名鼎鼎的红黑树,你get了么?2-3树 绝对平衡 右旋转 左旋转 颜色反转 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

  前言

  11.1新的一月加油!這個(gè)購物狂歡的季節(jié),一看,已囊中羞澀!趕緊來惡補(bǔ)一下紅黑樹和2-3樹吧!紅黑樹真的算是大名鼎鼎了吧?即使你不了解它,但一定聽過吧?下面跟隨我來揭開神秘的面紗吧!

  一、2-3樹

  1、搶了紅黑樹的光環(huán)?

  今天的主角是紅黑樹,是無疑的,主角光環(huán)在呢!那2-3樹又是什么鬼呢?學(xué)習(xí)2-3樹不僅對(duì)理解紅黑樹有幫助,對(duì)理解B類樹,也是有巨大幫助的,所以學(xué)習(xí)2-3樹很必要!

  2、基本性質(zhì)

  2-3樹滿足二分搜索樹的基本性質(zhì),但節(jié)點(diǎn)可以存放一個(gè)元素或兩個(gè)元素!如下圖,就是2-3樹:

  

  說明:2-3樹一顆絕對(duì)平衡的樹(絕對(duì)平衡:對(duì)于任意一個(gè)節(jié)點(diǎn),左右子樹高度相同)

  3、維護(hù)絕對(duì)平衡

  2-3樹在插入過程中如何維護(hù)絕對(duì)平衡呢?進(jìn)行畫圖演示,實(shí)在有點(diǎn)不好畫,如下圖:

  

  說明:

  1、不能將新節(jié)點(diǎn)插入到空節(jié)點(diǎn)

    因?yàn)槟菢尤缟蠄D,就不滿足絕對(duì)平衡了,所以可以將37和42合并,2-3支持3節(jié)點(diǎn)。

  2、不支持4節(jié)點(diǎn),進(jìn)行拆分

    再插入12時(shí),也不能插入空節(jié)點(diǎn),也要合并,但2-3樹不支持4節(jié)點(diǎn),所以進(jìn)行進(jìn)行拆分。

  3、子節(jié)點(diǎn)達(dá)到3節(jié)點(diǎn),合并到父節(jié)點(diǎn)

    再依次插入18、6,達(dá)到4節(jié)點(diǎn),進(jìn)行拆分,但不符合絕對(duì)平衡了怎么辦?將12和37合并,就形成了最后3節(jié)點(diǎn)的圖了

  總結(jié):講到這里,應(yīng)該對(duì)2-3樹如何維護(hù)絕對(duì)平衡,應(yīng)該了解了吧?理解2-3樹,對(duì)于再理解紅黑樹,是非常有幫助的,其實(shí),它們有等價(jià)性的,接下來會(huì)說明的。

  二、紅黑樹

  1、紅黑樹和2-3樹的等價(jià)性

  也想達(dá)到像2-3樹那樣的絕對(duì)平衡,但2-3樹的實(shí)現(xiàn)比較麻煩,所以產(chǎn)生了紅黑樹;那么,紅黑樹和2-3樹有怎么樣的等價(jià)性呢?如下圖:

  

  說明:紅黑樹最開始想用紅線區(qū)別b、c,但實(shí)現(xiàn)起來比較困難,然后用紅黑來表示節(jié)點(diǎn),就比較好實(shí)現(xiàn)了!

  紅黑樹和2-3樹總體對(duì)比圖,可以參考一下:

  

  2、紅黑樹5個(gè)重要性質(zhì)

  1、引自《算法導(dǎo)論》

  紅黑樹有五個(gè)重要性質(zhì),引自算法界一本圣潔《算法導(dǎo)論》中的內(nèi)容,如下:

  

  是不是看著有點(diǎn)暈,下面我進(jìn)行解釋。

  2、5個(gè)重要性質(zhì)

  1、每一個(gè)節(jié)點(diǎn)或者紅色的,或是黑色的

  2、根節(jié)點(diǎn)是黑色的

  3、每一個(gè)葉子節(jié)點(diǎn)(最后的空節(jié)點(diǎn))是黑色的

  4、如果一個(gè)節(jié)點(diǎn)是紅色的,那么它的孩子節(jié)點(diǎn)都是黑色的

  5、從任意節(jié)點(diǎn)到葉子節(jié)點(diǎn),經(jīng)過的黑色節(jié)點(diǎn)是一樣的

  

  解釋:最重要的性質(zhì)是第五條,前4條在理解2-3樹之后,就很好理解了,第5條性質(zhì)說明了:紅黑樹是保持“黑平衡”的二叉樹;

嚴(yán)格意義上來說,紅黑樹不是平衡二叉樹,最大高度:2logn,但是時(shí)間復(fù)雜度仍然是O(logn),因?yàn)?是常數(shù),但比AVL樹查詢要稍微慢一些。

  三、紅黑樹添加元素

  紅黑樹添加元素,比較繁瑣,因?yàn)橐3稚厦娴奈鍌€(gè)性質(zhì),要不然就不是紅黑樹了;

  1、保持根節(jié)點(diǎn)為節(jié)點(diǎn)

  紅黑樹的節(jié)點(diǎn)類也可以從二分搜索樹上進(jìn)行修改,但要新增“color”成員變量,來標(biāo)注節(jié)點(diǎn)顏色,節(jié)點(diǎn)類如下:

?

template<typename Key, typename Value> class RBTree { private:static const bool RED = true;static const bool BLACK = false;struct Node {Key key;Value value;Node *left;Node *right;bool color;Node(Key key, Value value) {this->key = key;this->value = value;this->left = this->right = nullptr;color = RED;  //默認(rèn)初始化為紅色}Node(Node *node) {this->key = node->key;this->value = node->value;this->left = node->left;this->right = node->right;this->color = node->color;}};Node *root;int size; }

  因?yàn)榧t黑樹性質(zhì)1要求根節(jié)點(diǎn)為黑色,所以要保持根節(jié)點(diǎn)為黑色;

  2、左旋轉(zhuǎn)

  像AVL樹一樣,紅黑樹也需要左旋和右旋,如下圖就需要左旋轉(zhuǎn),因?yàn)椤凹t色節(jié)點(diǎn)是左傾斜的”:

  

  說明:圖中黑色字體標(biāo)識(shí)黑色節(jié)點(diǎn),紅色表示紅色節(jié)點(diǎn),并演示了旋轉(zhuǎn)過程,最后還要改變節(jié)點(diǎn)顏色。

  3、左旋轉(zhuǎn)代碼實(shí)現(xiàn)

  代碼如下:

  

Node *leftRotate(Node *node) {Node *x = node->right;node->right = x->left;x->left = node;x->color = node->color;node->color = RED;return x;}

  4、顏色反轉(zhuǎn)

  下面這種情況就需要顏色反轉(zhuǎn),如下圖:

  

  

  5、顏色反轉(zhuǎn)代碼實(shí)現(xiàn)

  代碼如下:

void flipColors(Node *node) {node->color = RED;node->left->color = BLACK;node->right->color = BLACK;}

  6、右旋轉(zhuǎn)

  下面情況需要右旋轉(zhuǎn),如下圖:

  

    旋轉(zhuǎn)之后,如下圖:

  

?

   7、右旋轉(zhuǎn)代碼如下

  代碼如下:

  

Node *rightRotate(Node *node) {Node *x = node->left;node->left = x->right;x->right = node;x->color = node->color;node->color = RED;return x;}

  8、總體流程圖

  

  9、總體代碼

  總體代碼如下,供參考和學(xué)習(xí):

#ifndef RED_BLACK_TREE_RBTREE_H #define RED_BLACK_TREE_RBTREE_H#include <iostream> #include <vector>template<typename Key, typename Value> class RBTree { private:static const bool RED = true;static const bool BLACK = false;struct Node {Key key;Value value;Node *left;Node *right;bool color;Node(Key key, Value value) {this->key = key;this->value = value;this->left = this->right = nullptr;color = RED;}Node(Node *node) {this->key = node->key;this->value = node->value;this->left = node->left;this->right = node->right;this->color = node->color;}};Node *root;int size;public:RBTree() {root = nullptr;size = 0;}~RBTree() {destroy(root);}int getSize() {return size;}int isEmpty() {return size == 0;}bool isRed(Node *node) {if (node == nullptr) {return BLACK;}return node->color;}void add(Key key, Value value) {root = add(root, key, value);root->color = BLACK;}bool contains(Key key) {return getNode(root, key) != nullptr;}Value *get(Key key) {Node *node = getNode(root, key);return node == nullptr ? nullptr : &(node->value);}void set(Key key, Value newValue) {Node *node = getNode(root, key);if (node != nullptr) {node->value = newValue;}}private:// 向以node為根的二叉搜索樹中,插入節(jié)點(diǎn)(key, value)// 返回插入新節(jié)點(diǎn)后的二叉搜索樹的根Node *add(Node *node, Key key, Value value) {if (node == nullptr) {size++;return new Node(key, value);}if (key == node->key) {node->value = value;} else if (key < node->key) {node->left = add(node->left, key, value);} else {node->right = add(node->right, key, value);}if (isRed(node->right) && !isRed(node->left)) {node = leftRotate(node);}if (isRed(node->left) && isRed(node->left->left)) {node = rightRotate(node);}if (isRed(node->left) && isRed(node->right)) {flipColors(node);}return node;}// 在以node為根的二叉搜索樹中查找key所對(duì)應(yīng)的NodeNode *getNode(Node *node, Key key) {if (node == nullptr) {return nullptr;}if (key == node->key) {return node;} else if (key < node->key) {return getNode(node->left, key);} else {return getNode(node->right, key);}}void destroy(Node *node) {if (node != nullptr) {destroy(node->left);destroy(node->right);delete node;size--;}}Node *leftRotate(Node *node) {Node *x = node->right;node->right = x->left;x->left = node;x->color = node->color;node->color = RED;return x;}Node *rightRotate(Node *node) {Node *x = node->left;node->left = x->right;x->right = node;x->color = node->color;node->color = RED;return x;}void flipColors(Node *node) {node->color = RED;node->left->color = BLACK;node->right->color = BLACK;} };#endif //RED_BLACK_TREE_RBTREE_H View Code

  總結(jié)  

  面試時(shí)99.9%不會(huì)讓手寫一下紅黑樹的添加過程,除非你面試算法工程師,那就打擾了!主要理解紅黑樹的性質(zhì)、左旋和右旋等。

  歡迎點(diǎn)贊和評(píng)論,感謝支持!

轉(zhuǎn)載于:https://www.cnblogs.com/liudw-0215/p/9887951.html

總結(jié)

以上是生活随笔為你收集整理的大名鼎鼎的红黑树,你get了么?2-3树 绝对平衡 右旋转 左旋转 颜色反转的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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