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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

数据结构-----红黑树的插入操作

發(fā)布時(shí)間:2024/4/19 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构-----红黑树的插入操作 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

紅黑樹是一棵二叉搜索樹;樹種每一個(gè)節(jié)點(diǎn)的顏色不是黑色就是紅色。本篇中只實(shí)現(xiàn)用節(jié)點(diǎn)的顏色來描述紅黑樹,性質(zhì)如下:

RB1:根節(jié)點(diǎn)和所有外部節(jié)點(diǎn)都是黑色;

RB2:在根至外部節(jié)點(diǎn)路徑上,沒有連續(xù)兩個(gè)節(jié)點(diǎn)是紅色;

RB3:在所有根至外部節(jié)點(diǎn)的路徑上,黑色節(jié)點(diǎn)的數(shù)目都相同;


實(shí)現(xiàn)紅黑樹,首先需要定義樹節(jié)點(diǎn),節(jié)點(diǎn)包括:

1:節(jié)點(diǎn)顏色,黑色或者白色,用整型或者布爾類型表示,也可以預(yù)設(shè)兩個(gè)宏;

2:節(jié)點(diǎn)權(quán)值,用來保存節(jié)點(diǎn)的數(shù)據(jù);

3:左右子樹指針;


首先是紅黑樹的定義,本例中紅黑樹繼承自BST(二叉搜索樹),即:

#define BLACK 1 #define RED 0template<class T> class RBTree : public binarySearchTree<T, int> { public:RBTree() : binarySearchTree() {}~RBTree() {}void insert(const T& key) {insert(root, key);}void remove(const T& key) {remove(root, key);}private:binaryTreeNode<pair<const T, int>>*insert(binaryTreeNode<pair<const T, int>>*&, const T&);binaryTreeNode<pair<const T, int>>*remove(binaryTreeNode<pair<const T, int>>*&, const T&);binaryTreeNode<pair<const T, int>>*maximun(binaryTreeNode<pair<const T, int>>*);binaryTreeNode<pair<const T, int>>*minimun(binaryTreeNode<pair<const T, int>>*);int color(binaryTreeNode<pair<const T, int>>*);}
和AVL樹類似,插入刪除操作也是利用遞歸實(shí)現(xiàn),所以在私有成員中存在實(shí)現(xiàn)遞歸調(diào)用的重載函數(shù)。

模板參數(shù)T為節(jié)點(diǎn)權(quán)值的類型,int為顏色類型。

insert插入函數(shù):在以該節(jié)點(diǎn)為根節(jié)點(diǎn)的子樹中插入新權(quán)值,返回插入后該子樹的根節(jié)點(diǎn)。

remove刪除操作:在以該節(jié)點(diǎn)為根節(jié)點(diǎn)的子樹中刪除特定權(quán)值的節(jié)點(diǎn),返回刪除后子樹的根節(jié)點(diǎn)。

maximun函數(shù):返回以該節(jié)點(diǎn)為根節(jié)點(diǎn)的子樹中權(quán)值最大的節(jié)點(diǎn)。

minimun函數(shù):返回以該節(jié)點(diǎn)為根節(jié)點(diǎn)的子樹中權(quán)值最小的節(jié)點(diǎn)。

color函數(shù):返回函數(shù)的顏色。


template<class T> int RBTree<T>::color(binaryTreeNode<pair<const T,int>>* pnode) {if(pnode == NULL)return BLACK;return pnode->element.second; }


插入操作步驟如下:
步驟1:找到待插入的位置,即逐個(gè)比較權(quán)值,若該節(jié)點(diǎn)權(quán)值小于待插入權(quán)值,則在右子樹中插入;若該節(jié)點(diǎn)權(quán)值大于待插入權(quán)值,則在左子樹中插入。

步驟2:申請(qǐng)新節(jié)點(diǎn),若樹為空,則新節(jié)點(diǎn)為黑色;若樹非空,則新節(jié)點(diǎn)為紅色。

步驟3:改變相關(guān)節(jié)點(diǎn)的顏色,調(diào)整樹平衡。


申請(qǐng)新節(jié)點(diǎn)的代碼如下:

template<class T> binaryTreeNode<pair<const T, int>>* RBTree<T>::insert(binaryTreeNode<pair<const T, int>>* &pnode, const T& key) {if(pnode == NULL){if(root == NULL)pnode = new binaryTreeNode<pair<const T, int>>*(pair<const T, int>(key, BLACK));elsepnode = new binaryTreeNode<pair<const T, int>>*(pair<const T, int>(key, RED)); }/*...*/ }
接下來就是執(zhí)行比較插入的過程,涉及到對(duì)節(jié)點(diǎn)顏色進(jìn)行修改的內(nèi)容,我們先了解一下需要哪些調(diào)整。

插入操作的樹平衡被破壞無非是存在兩個(gè)連續(xù)的紅色節(jié)點(diǎn),違反了RB2。

同時(shí),若違反RB2,則新插入節(jié)點(diǎn)和其父節(jié)點(diǎn)都應(yīng)為紅色,那么祖父節(jié)點(diǎn)必須為黑色(因?yàn)椴迦胫笆瞧胶獾?#xff09;。

被破壞的情況有以下幾種,假設(shè)子樹的根節(jié)點(diǎn)為pnode,插入的節(jié)點(diǎn)為ptNode:


第一種情況:pnode的左孩子和右孩子都為紅色,新節(jié)點(diǎn)是pnode孩子的孩子。

插入節(jié)點(diǎn)為pnode->leftChild->leftChild或pnode->leftChild->rightChild color(pnode->leftChild) == RED && color(pnode->rightChild) == RED 或者 插入節(jié)點(diǎn)為pnode->rightChild->leftChild或pnode->rightChild->rightChild color(pnode->rightChild) == RED && color(pnode->leftChild) == RED 解決方案:

1:將根節(jié)點(diǎn)的左右子樹的顏色涂上黑色;

2:若pnode不是整個(gè)紅黑樹的根節(jié)點(diǎn),則將pnode涂上紅色

3:返回pnode;

代碼實(shí)現(xiàn):

template<class T> binaryTreeNode<pair<const T,int>>* RBTree<T>::rModify(binaryTreeNode<pair<const T, int>>* pnode) {pnode->leftChild->element.second = BLACK;pnode->rightChild->element.second = BLACK;if(pnode != root)pnode->element.second = RED;return pnode; }

第二種情況:pnode的左孩子為紅色,右孩子為黑色(也可以是外部節(jié)點(diǎn)),新節(jié)點(diǎn)是pnode左孩子的孩子。

插入節(jié)點(diǎn)為pnode->leftChild->leftChild或pnode->leftChild->rightChild color(pnode->leftChild) == RED && color(pnode->rightChild) == BLACK 解決方案:

1:若插入的是pnode左孩子的左孩子,則進(jìn)行右旋操作;若插入的是pnode左孩子的右孩子,則進(jìn)行先左旋后右旋操作;此時(shí)pnode為新根節(jié)點(diǎn)。

2:將新的根節(jié)點(diǎn)涂黑,將新根節(jié)點(diǎn)右孩子涂紅。

3:返回根節(jié)點(diǎn)。

代碼實(shí)現(xiàn):

template<class T> binaryTreeNode<pair<const T,int>>* RBTree<T>::LbModify(binaryTreeNode<pair<const T, int>>* pnode) {pnode->element.second = BLACK;pnode->rightChild->element.second = RED;return pnode; }函數(shù)調(diào)用:

if(color(pnode->rightChild) == BLACK && color(pnode->leftChild) == RED) {if(key > pnode->leftChild->element.first)pnode = leftRightRotation(pnode);elsepnode = rightRotation(pnode);pnode = LbModify(pnode); }

第三種情況:pnode的右孩子為紅色,左孩子為黑色,新節(jié)點(diǎn)為pnode右孩子的孩子。

插入節(jié)點(diǎn)為pnode->rightChild->leftChild或pnode->rightChild->rightChild color(pnode->rightChild) == RED && color(pnode->leftChild) == BLACK

解決方案:

1:若新節(jié)點(diǎn)是pnode右孩子的右孩子,進(jìn)行左旋操作;若新節(jié)點(diǎn)是pnode右孩子的左孩子,進(jìn)行先右旋后左旋操作,此時(shí)pnode為新的根節(jié)點(diǎn)。

2:將新的根節(jié)點(diǎn)涂黑,新根節(jié)點(diǎn)的左孩子涂紅。

3:返回新根節(jié)點(diǎn)。

代碼實(shí)現(xiàn):

template<class T> binaryTreeNode<pair<const T,int>>* RBTree<T>::RbModify(binaryTreeNode<pair<const T, int>>* pnode) {pnode->element.second = BLACK;pnode->leftChild->element.second = RED;return pnode; }調(diào)用代碼:

if(color(pnode->leftChild) == BLACK && color(pnode->rightChild) == RED) {if(key > pnode->rightChild->element.first)pnode = leftRotation(pnode);elsepnode = rightLeftRotation(pnode);pnode = RbModify(pnode); }
插入函數(shù)代碼:

template<class T> binaryTreeNode<pair<const T, int>>* RBTree<T>::insert(binaryTreeNode<pair<const T, int>>* &pnode, const T& key) {if(pnode == NULL) //申請(qǐng)新節(jié)點(diǎn),空則為黑色,非空則為紅色。{if(root == NULL)pnode = new binaryTreeNode<pair<const T, int>>*(pair<const T, int>(key, BLACK));elsepnode = new binaryTreeNode<pair<const T, int>>*(pair<const T, int>(key, RED)); }else{if(key < pnode->element.first){//如果key小,則在左子樹中插入pnode->leftChild = insert(pnode->leftChild, key);//左子樹中插入后,若左孩子的孩子是紅色,則需要進(jìn)一步判斷。if(pnode->leftChild->leftChild != NULL && color(pnode->leftChild->leftChild) == RED)||(pnode->leftChild->rightChild != NULL && color(pnode->leftChild->rightChild) == RED){//若左孩子是紅色,則需要調(diào)整if(color(pnode->leftChild) == RED){if(color(pnode->rightChild) == RED) //若右孩子是黑色,為第一種情況pnode = rModify(pnode);else //否則,為第二種或者第三種{if(key > pnode->leftChild->element.first)pnode = leftRightRotation(pnode);elsepnode = rightRotation(pnode);pnode = LbModify(pnode);}}}}//與上述對(duì)稱else if(key > pnode->element.first){pnode->rightChild = insert(pnode->rightChild, key);if(pnode->rightChild->leftChild != NULL && color(pnode->rightChild->leftChild) == RED) ||(pnode->rightChild->rightChild != NULL && color(pnode->rightChild->rightChild) == RED){if(color(pnode->rightChild) == RED){if(color(pnode->leftChild) == RED)pnode = rModify(pnode);else{if(key > pnode->rightChild->element.first)pnode = leftRotation(pnode);elsepnode = rightLeftRotation(pnode);pnode = RbModify(pnode);}}}}}return pnode; }





總結(jié)

以上是生活随笔為你收集整理的数据结构-----红黑树的插入操作的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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