中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

做網(wǎng)站要怎么備案網(wǎng)站建設(shè)是什么

做網(wǎng)站要怎么備案,網(wǎng)站建設(shè)是什么,傳奇網(wǎng)站建設(shè),一個(gè)公司做多個(gè)網(wǎng)站前言:本篇文章我們繼續(xù)來(lái)分享C中的另一個(gè)復(fù)雜數(shù)據(jù)結(jié)構(gòu)——紅黑樹。 目錄 一.紅黑樹概念 二.紅黑樹性質(zhì) 三.紅黑樹實(shí)現(xiàn) 1.基本框架 2.插入 3.判斷平衡 四.完整代碼 總結(jié) 一.紅黑樹概念 紅黑樹,是一種二叉搜索樹,但在每個(gè)結(jié)點(diǎn)上增加一個(gè)…

前言:本篇文章我們繼續(xù)來(lái)分享C++中的另一個(gè)復(fù)雜數(shù)據(jù)結(jié)構(gòu)——紅黑樹。


目錄

一.紅黑樹概念

二.紅黑樹性質(zhì)

三.紅黑樹實(shí)現(xiàn)

1.基本框架

2.插入

3.判斷平衡

?四.完整代碼

總結(jié)


一.紅黑樹概念

紅黑樹,是一種二叉搜索樹,但在每個(gè)結(jié)點(diǎn)上增加一個(gè)存儲(chǔ)位表示結(jié)點(diǎn)的顏色,可以是RedBlack。 通過(guò)對(duì)任何一條從根到葉子的路徑上各個(gè)結(jié)點(diǎn)著色方式的限制,紅黑樹確保沒有一條路徑會(huì)比其他路徑長(zhǎng)出兩倍,因而是接近平衡的。


二.紅黑樹性質(zhì)

  1. 每個(gè)結(jié)點(diǎn)不是紅色就是黑色

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

  3. 如果一個(gè)節(jié)點(diǎn)是紅色的,則它的兩個(gè)孩子結(jié)點(diǎn)是黑色的(不存在連續(xù)的紅色節(jié)點(diǎn))?

  4. 對(duì)于每個(gè)結(jié)點(diǎn),從該結(jié)點(diǎn)到其所有后代葉結(jié)點(diǎn)的簡(jiǎn)單路徑上,均包含相同數(shù)目的黑色結(jié)點(diǎn)(每條路徑都存在相同數(shù)量的黑色節(jié)點(diǎn))?

  5. 每個(gè)葉子結(jié)點(diǎn)都是黑色的(此處的葉子結(jié)點(diǎn)指的是空結(jié)點(diǎn)NULL)

如何理解紅黑樹最長(zhǎng)路徑不超過(guò)最短路徑的二倍呢???

  1. ?從性質(zhì)能夠看出,紅黑樹每一條路徑上,都有相同數(shù)量的黑色節(jié)點(diǎn)
  2. 紅黑樹每條路徑上可以存在連續(xù)的黑色節(jié)點(diǎn),但不能存在連續(xù)的紅色節(jié)點(diǎn)。
  3. 所以最短路徑即為全是黑色節(jié)點(diǎn)的路徑。
  4. 最長(zhǎng)路徑則為一黑一紅相間的路徑。

三.紅黑樹實(shí)現(xiàn)

1.基本框架

紅黑樹與AVL樹相比,多了節(jié)點(diǎn)顏色這一信息,為了實(shí)現(xiàn)這一信息,我們使用枚舉

enum Colour
{RED,BLACK
};template<class K,class V>
struct RBTreeNode
{RBTreeNode<K, V>* _left;RBTreeNode<K, V>* _right;RBTreeNode<K, V>* _parent;pair<K, V> _kv;Colour _col;RBTreeNode(const pair<K, V>& kv):_left(nullptr), _right(nullptr), _parent(nullptr), _kv(kv),_col(RED){}
};
template<class K, class V>
class RBTree
{typedef RBTreeNode<K, V> Node;
public:private:Node* _root = nullptr;size_t _size = 0;
};

同時(shí)我們多創(chuàng)建一個(gè)_size成員變量,用于記錄節(jié)點(diǎn)數(shù)量。?


2.插入

紅黑樹插入的基本步驟與二叉搜索樹和AVL樹一樣,都是按照左子節(jié)點(diǎn)比根節(jié)點(diǎn)小,右子節(jié)點(diǎn)比根節(jié)點(diǎn)大的規(guī)則,唯一不同的是,紅黑樹的插入要考慮其性質(zhì)。其中最值得注意的性質(zhì)為:

  1. 不存在連續(xù)的紅節(jié)點(diǎn)
  2. 每條路徑上的黑節(jié)點(diǎn)數(shù)相等

?其中能夠看出,第二條才是最關(guān)鍵的,因此我們每次新插入節(jié)點(diǎn)時(shí),必須插入紅節(jié)點(diǎn)。

此時(shí)我們會(huì)面臨兩種情況

  1. 父節(jié)點(diǎn)為黑色,插入即結(jié)束,無(wú)需調(diào)整。
  2. 父節(jié)點(diǎn)為紅色,不滿足上述性質(zhì)1,需要調(diào)整。

下面我們來(lái)看特殊情況:

父親為紅節(jié)點(diǎn),那么只有將父節(jié)點(diǎn)變?yōu)楹谏?jié)點(diǎn),才能夠滿足性質(zhì)。

但是如果父親變?yōu)楹诠?jié)點(diǎn),就說(shuō)明該路徑上同樣多出一個(gè)黑節(jié)點(diǎn),而唯一的處理手段,就是讓父親的父親,也就是爺爺節(jié)點(diǎn),變?yōu)榧t色節(jié)點(diǎn)。

此時(shí)又存在問題,那就是關(guān)于父親的兄弟節(jié)點(diǎn),也就是叔叔節(jié)點(diǎn),那么叔叔節(jié)點(diǎn)存在三種情況

  1. 叔叔節(jié)點(diǎn)同樣為紅色。
  2. 叔叔節(jié)點(diǎn)不存在。
  3. 叔叔節(jié)點(diǎn)為黑色。

如果叔叔節(jié)點(diǎn)為紅色,為了滿足各路徑黑節(jié)點(diǎn)數(shù)量相同,叔叔節(jié)點(diǎn)則需要和父節(jié)點(diǎn)一起變?yōu)楹谏?/span>。

如果叔叔節(jié)點(diǎn)不存在,為了滿足性質(zhì),需要將該子樹從爺爺節(jié)點(diǎn)的位置進(jìn)行旋轉(zhuǎn)。

如果叔叔節(jié)點(diǎn)為黑色,而父節(jié)點(diǎn)為紅色,如果還要滿足性質(zhì),說(shuō)明子節(jié)點(diǎn)原本應(yīng)為黑色,是因?yàn)榻?jīng)過(guò)了上述的調(diào)整而作為爺爺節(jié)點(diǎn)變成了紅色。此時(shí)我們仍需從爺爺節(jié)點(diǎn)的位置進(jìn)行旋轉(zhuǎn)。

分析完上述完整情況之后,還有關(guān)于新插入節(jié)點(diǎn)的兩種情況

  1. 父節(jié)點(diǎn)為爺爺節(jié)點(diǎn)的左子節(jié)點(diǎn),同時(shí)新增節(jié)點(diǎn)也為父節(jié)點(diǎn)的左子節(jié)點(diǎn),為一條斜線。
  2. 父節(jié)點(diǎn)為爺爺節(jié)點(diǎn)的左子節(jié)點(diǎn),但是新增節(jié)點(diǎn)也為父節(jié)點(diǎn)的有子節(jié)點(diǎn),為一條折線。

斜線情況下,我們?cè)谛枰D(zhuǎn)時(shí)只需單旋即可;

而當(dāng)為折線時(shí),就需要進(jìn)行雙旋,先變?yōu)樾本€,在進(jìn)行調(diào)整。

同時(shí)父節(jié)點(diǎn)也需要考慮是爺爺節(jié)點(diǎn)的左節(jié)點(diǎn)還是右節(jié)點(diǎn)兩種情況,彼此的規(guī)則相反。

按照上邊的步驟,我們能夠得出代碼情況:

//插入bool Insert(const pair<K,V>& kv){if (_root == nullptr){_root = new Node(kv);_root->_col = BLACK;//根給黑色return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_kv.first < kv.first){parent = cur;cur = cur->_right;}else if (cur->_kv.first > kv.first){parent = cur;cur = cur->_left;}else{return false;}}cur = new Node(kv);cur->_col = RED;//新增節(jié)點(diǎn)給紅色if (kv.first < parent->_kv.first){parent->_left = cur;}else{parent->_right = cur;}cur->_parent = parent;//parent是黑色就結(jié)束while (parent && parent->_col == RED){Node* Grandfather = parent->_parent;if (parent == Grandfather->_left){Node* uncle = Grandfather->_right;if (uncle && uncle->_col == RED)//叔叔存在且為紅,直接變色{parent->_col = BLACK;uncle->_col = BLACK;Grandfather->_col = RED;//繼續(xù)往上處理cur = Grandfather;parent = Grandfather->_parent;}else//叔叔不存在或叔叔存在但為黑{if (cur == parent->_left)//左邊直接右旋{RotateR(Grandfather);parent->_col = BLACK;Grandfather->_col = RED;}else//右邊則左右雙旋{RotateL(parent);RotateR(Grandfather);cur->_col = BLACK;Grandfather->_col = RED;}break;}}else{Node* uncle = Grandfather->_left;if (uncle && uncle->_col == RED){parent->_col = BLACK;uncle->_col = BLACK;Grandfather->_col = RED;cur = Grandfather;parent = Grandfather->_parent;}else{if (cur == parent->_right){RotateL(Grandfather);Grandfather->_col = RED;parent->_col = BLACK;}else{RotateR(parent);RotateL(Grandfather);cur->_col = BLACK;Grandfather->_col = RED;}break;}}}_root->_col = BLACK;return true;}

?需要考慮的情況確實(shí)很多,但如果自己畫圖認(rèn)真分析,理解起來(lái)還是易如反掌的


3.判斷平衡

判斷紅黑樹的平衡,我們自然要從其性質(zhì)入手:

  1. 首先就是判斷根節(jié)點(diǎn)是否為黑色。
  2. 其次容易判斷的是是否有兩個(gè)相鄰的紅色節(jié)點(diǎn),注意這里我們不去判斷一個(gè)節(jié)點(diǎn)與其子節(jié)點(diǎn),反而去判斷一個(gè)節(jié)點(diǎn)與其父節(jié)點(diǎn)。因?yàn)?span style="color:#ff9900;">如果判斷子節(jié)點(diǎn),則可能需要判斷兩次,而父節(jié)點(diǎn)則只需判斷一次。
  3. 最后就是判斷所有路徑上的黑節(jié)點(diǎn)數(shù)量是否相同。

其中前兩種都比較容易想到代碼方式,最重要的是如何比較黑節(jié)點(diǎn)的數(shù)量。

我們可以通過(guò)增加參數(shù)的方式。來(lái)記錄到達(dá)每個(gè)節(jié)點(diǎn)位置時(shí),該路徑上出現(xiàn)過(guò)的黑節(jié)點(diǎn)的數(shù)量。而如何進(jìn)行比較,因?yàn)槊織l路徑上黑節(jié)點(diǎn)的數(shù)量都必須相同,所以我們直接記錄一下最左邊的一條路徑上黑節(jié)點(diǎn)的數(shù)量,然后求出一條路徑上的黑節(jié)點(diǎn)數(shù)之后,就進(jìn)行比較即可

	//判斷平衡bool IsBalance(){if (_root->_col == RED)return false;int refnum = 0;Node* cur = _root;while (cur){if (cur->_col == BLACK)refnum++;cur = cur->_left;}return Check(_root, 0, refnum);}bool Check(Node* root, int BlackNum,const int refnum){if (root == nullptr){if (refnum != BlackNum){cout << "存在黑色節(jié)點(diǎn)個(gè)數(shù)不相等" << endl;return false;}cout << BlackNum << endl;return true;}if (root->_col == RED && root->_parent->_col == RED){cout << root->_kv.first << "->存在連續(xù)的紅色節(jié)點(diǎn)" << endl;return false;}if (root->_col == BLACK)BlackNum++;return Check(root->_left, BlackNum,refnum)&& Check(root->_right, BlackNum,refnum);}

?四.完整代碼

enum Colour
{RED,BLACK
};template<class K,class V>
struct RBTreeNode
{RBTreeNode<K, V>* _left;RBTreeNode<K, V>* _right;RBTreeNode<K, V>* _parent;pair<K, V> _kv;Colour _col;RBTreeNode(const pair<K, V>& kv):_left(nullptr), _right(nullptr), _parent(nullptr), _kv(kv),_col(RED){}
};
template<class K, class V>
class RBTree
{typedef RBTreeNode<K, V> Node;
public://插入bool Insert(const pair<K,V>& kv){if (_root == nullptr){_root = new Node(kv);_root->_col = BLACK;//根給黑色return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_kv.first < kv.first){parent = cur;cur = cur->_right;}else if (cur->_kv.first > kv.first){parent = cur;cur = cur->_left;}else{return false;}}cur = new Node(kv);cur->_col = RED;//新增節(jié)點(diǎn)給紅色if (kv.first < parent->_kv.first){parent->_left = cur;}else{parent->_right = cur;}cur->_parent = parent;//parent是黑色就結(jié)束while (parent && parent->_col == RED){Node* Grandfather = parent->_parent;if (parent == Grandfather->_left){Node* uncle = Grandfather->_right;if (uncle && uncle->_col == RED)//叔叔存在且為紅,直接變色{parent->_col = BLACK;uncle->_col = BLACK;Grandfather->_col = RED;//繼續(xù)往上處理cur = Grandfather;parent = Grandfather->_parent;}else//叔叔不存在或叔叔存在但為黑{if (cur == parent->_left)//左邊直接右旋{RotateR(Grandfather);parent->_col = BLACK;Grandfather->_col = RED;}else//右邊則左右雙旋{RotateL(parent);RotateR(Grandfather);cur->_col = BLACK;Grandfather->_col = RED;}break;}}else{Node* uncle = Grandfather->_left;if (uncle && uncle->_col == RED){parent->_col = BLACK;uncle->_col = BLACK;Grandfather->_col = RED;cur = Grandfather;parent = Grandfather->_parent;}else{if (cur == parent->_right){RotateL(Grandfather);Grandfather->_col = RED;parent->_col = BLACK;}else{RotateR(parent);RotateL(Grandfather);cur->_col = BLACK;Grandfather->_col = RED;}break;}}}_root->_col = BLACK;return true;}//右單旋void RotateR(Node* parent){//定義左子節(jié)點(diǎn)Node* subL = parent->_left;//定義左子節(jié)點(diǎn)的右子節(jié)點(diǎn)Node* subLR = subL->_right;//調(diào)整parent->_left = subLR;//判空if (subLR)subLR->_parent = parent;//調(diào)整subL->_right = parent;Node* ppNode = parent->_parent;parent->_parent = subL;if (parent == _root)//判斷是否為根{_root = subL;_root->_parent = nullptr;}else//不是根節(jié)點(diǎn),調(diào)整父節(jié)點(diǎn)指向{if (ppNode->_left == parent)ppNode->_left = subL;elseppNode->_right = subL;subL->_parent = ppNode;}}//左單旋void RotateL(Node* parent){//定義右子節(jié)點(diǎn)Node* subR = parent->_right;//定義右子節(jié)點(diǎn)的左子節(jié)點(diǎn)Node* subRL = subR->_left;//調(diào)整parent->_right = subRL;//判空if (subRL)subRL->_parent = parent;//調(diào)整subR->_left = parent;Node* ppNode = parent->_parent;parent->_parent = subR;if (parent == _root)//判斷是否為根{_root = subR;_root->_parent = nullptr;}else//不是根節(jié)點(diǎn),調(diào)整父節(jié)點(diǎn)指向{if (ppNode->_left == parent)ppNode->_left = subR;elseppNode->_right = subR;subR->_parent = ppNode;}}//遍歷void InOrder(){inOrder(_root);cout << endl;}void inOrder(const Node* root){if (root == nullptr){return;}inOrder(root->_left);cout << root->_kv.first << ':' << root->_kv.second << endl;inOrder(root->_right);}//判斷平衡bool IsBalance(){if (_root->_col == RED)return false;int refnum = 0;Node* cur = _root;while (cur){if (cur->_col == BLACK)refnum++;cur = cur->_left;}return Check(_root, 0, refnum);}bool Check(Node* root, int BlackNum,const int refnum){if (root == nullptr){if (refnum != BlackNum){cout << "存在黑色節(jié)點(diǎn)個(gè)數(shù)不相等" << endl;return false;}cout << BlackNum << endl;return true;}if (root->_col == RED && root->_parent->_col == RED){cout << root->_kv.first << "->存在連續(xù)的紅色節(jié)點(diǎn)" << endl;return false;}if (root->_col == BLACK)BlackNum++;return Check(root->_left, BlackNum,refnum)&& Check(root->_right, BlackNum,refnum);}
private:Node* _root = nullptr;//size_t _size = 0;
};

總結(jié)

關(guān)于紅黑樹的知識(shí)就分享這么多,喜歡本篇文章記得一鍵三連,我們下期再見!

http://www.risenshineclean.com/news/38654.html

相關(guān)文章:

  • 新華書店的做的數(shù)字閱讀網(wǎng)站51外鏈代發(fā)網(wǎng)
  • 建網(wǎng)站公司用什么網(wǎng)站程序濟(jì)南百度競(jìng)價(jià)開戶
  • 網(wǎng)站制作與網(wǎng)頁(yè)設(shè)計(jì)seo公司軟件
  • 一站式服務(wù)理念打廣告推廣怎么做
  • 網(wǎng)站開發(fā) 價(jià)格差異百度號(hào)碼認(rèn)證平臺(tái)官網(wǎng)首頁(yè)
  • 自己做soho需要做網(wǎng)站嗎長(zhǎng)春網(wǎng)站制作公司
  • 網(wǎng)站建設(shè)公司怎么免費(fèi)自己做推廣
  • 怎么做自己的網(wǎng)站自建一個(gè)頁(yè)面友情鏈接圖片
  • 貿(mào)易公司寮步網(wǎng)站建設(shè)哪家好怎么做好網(wǎng)站搜索引擎優(yōu)化
  • 廈門服裝商城網(wǎng)站建設(shè)優(yōu)化網(wǎng)站快速排名軟件
  • cpa單頁(yè)網(wǎng)站怎么做谷歌手機(jī)版瀏覽器官網(wǎng)
  • php網(wǎng)站開發(fā)是什么嗎廣州百度提升優(yōu)化
  • 鄧州網(wǎng)站制作seo1域名查詢
  • 推廣普通話喜迎二十手抄報(bào)seo鏈接優(yōu)化建議
  • 自己這么做網(wǎng)站semir是什么牌子
  • 麻涌公司網(wǎng)站建設(shè)公司百度云電腦網(wǎng)頁(yè)版入口
  • 電子商務(wù)網(wǎng)站建設(shè)合同范本外包公司排名
  • 自己在線制作logo免費(fèi)網(wǎng)站北京seo優(yōu)化廠家
  • 公司網(wǎng)站開發(fā)費(fèi)用計(jì)入什么科目營(yíng)銷公司
  • vs網(wǎng)站中的輪播怎么做軟文寫作技巧有哪些
  • 圖片1600px做網(wǎng)站武漢網(wǎng)優(yōu)化seo公司
  • 企業(yè)網(wǎng)站的建立主要用于企業(yè)內(nèi)部發(fā)布信息鄭州seo公司哪家好
  • 標(biāo)書制作教程視頻網(wǎng)站3322免費(fèi)域名注冊(cè)
  • 網(wǎng)站網(wǎng)址怎么找電商運(yùn)營(yíng)培訓(xùn)班多少錢
  • 彩票代購(gòu)網(wǎng)站建設(shè)電腦優(yōu)化軟件哪個(gè)好用
  • 以個(gè)人名義可以做網(wǎng)站嗎蘋果自研搜索引擎或?yàn)樘娲雀?/a>
  • 如果想看網(wǎng)站的收費(fèi)電影應(yīng)該怎么做惠州關(guān)鍵詞排名提升
  • 怎么把自己做的網(wǎng)站掛到外網(wǎng)上sem代運(yùn)營(yíng)
  • 2018年做返利網(wǎng)站網(wǎng)站功能優(yōu)化
  • 仿牌外貿(mào)網(wǎng)站百度搜索高級(jí)搜索