學習算法 仍是建議看看算法導論node
算法導論第三版 若是不看數學推導 僅看僞代碼 難度仍是適中ios
本系列只是記錄個人學習心得 和僞代碼轉化代碼的過程算法
深刻學習 仍是建議你們看看算法書籍 教程更加系統。函數
本文參考算法導論第13章節 紅黑樹性能
代碼由本人寫成學習
轉載請標明出處測試
紅黑樹是一個帶顏色的二叉樹spa
有如下5點性能3d
1 每一個節點或者紅色或者黑色指針
2 根節點黑色
3 每一個葉子節點(nil)爲黑色
4 若是一個節點是紅色的則它的兩個子節點都是黑色
5 每一個節點 該節點到子孫節點的路徑上 黑色節點數目相同
如圖
nil節點共享版本
隱藏nil節點
紅黑樹的結構與二叉樹相似
可是增長了指向節點父節點的指針 和顏色記錄
enum Color { red = 1, black }; struct node { Color color_; std::shared_ptr<node> left_; std::shared_ptr<node> right_; std::shared_ptr<node> parent_; int value_; node() { left_ = right_ = parent_ = nullptr; value_ = -1; color_ = black; } };
還建立以葉節點nil
std::shared_ptr<node> nil(new node);
打印函數 與二叉樹變化不大
void PrinTree(std::shared_ptr<node> root) { if (root == nil) { return; } std::cout << root->value_ << " "; if(root->left_!=nil) PrinTree(root->left_); if(root->right_ != nil) PrinTree(root->right_); }
旋轉操做
旋轉是保持平衡的最基本的操做 咱們先從這裏開始學習
在實際的操做旋轉如圖
僞代碼如圖
實際上就是
將Y的左子樹 更改成X的右子樹
X更改成Y的左子樹
實際代碼爲
void RightRotate(std::shared_ptr<node>& root, std::shared_ptr<node> x) { std::shared_ptr<node> y = x->left_; x->left_ = y->right_; if (y->right_ != nil) y->right_->parent_ = x; y->parent_ = x->parent_; if (x->parent_ == nil){ root = y; } else if (x->parent_->left_ == x) { x->parent_->left_ = y; } else { x->parent_->right_ = y; } y->right_ = x; x->parent_ = y; }
咱們來建立一個紅黑樹 測試下旋轉操做(先不關注顏色 只關注旋轉操做)
所有代碼以下
// rbShow.cpp : 定義控制檯應用程序的入口點。 // #include "stdafx.h" #include <memory> #include <iostream> using namespace std; enum Color { red = 1, black }; struct node { Color color_; std::shared_ptr<node> left_; std::shared_ptr<node> right_; std::shared_ptr<node> parent_; int value_; node() { left_ = right_ = parent_ = nullptr; value_ = -1; color_ = black; } }; std::shared_ptr<node> nil(new node); std::shared_ptr<node> CreateNode(Color color, int i) { std::shared_ptr<node> p(new node); p->color_ = color; p->left_ = nil; p->right_ = nil; p->parent_ = nil; p->value_ = i; return p; } void RightRotate(std::shared_ptr<node>& root, std::shared_ptr<node> x) { std::shared_ptr<node> y = x->left_; x->left_ = y->right_; if (y->right_ != nil) y->right_->parent_ = x; y->parent_ = x->parent_; if (x->parent_ == nil) { root = y; } else if (x->parent_->left_ == x) { x->parent_->left_ = y; } else { x->parent_->right_ = y; } y->right_ = x; x->parent_ = y; } void LeftRotate(std::shared_ptr<node>& root, std::shared_ptr<node> x) { std::shared_ptr<node> y = x->right_; x->right_ = y->left_; if (y->left_ != nil) y->left_->parent_ = x; y->parent_ = x->parent_; if (x->parent_ == nil) { root = y; } else if (x->parent_->left_ == x) { x->parent_->left_ = y; } else { x->parent_->right_ = y; } y->left_ = x; x->parent_ = y; } void PrinTree(std::shared_ptr<node> root) { if (root == nil) { return; } std::cout << root->value_ << " "; if (root->left_ != nil) PrinTree(root->left_); if (root->right_ != nil) PrinTree(root->right_); } void TestLeftRotate1() { std::shared_ptr<node> root = CreateNode(black, 1); root->parent_ = nil; std::shared_ptr<node> x = root; root->right_ = CreateNode(red, 2); root->right_->parent_ = root; PrinTree(root); std::cout << std::endl; LeftRotate(root, x); PrinTree(root); std::cout << std::endl; } void TestRightRotate1() { std::shared_ptr<node> root = CreateNode(black, 2); root->parent_ = nil; std::shared_ptr<node> x = root; std::shared_ptr<node> y = CreateNode(red, 1); root->left_ = y; y->parent_ = x; PrinTree(root); std::cout << std::endl; RightRotate(root, x); PrinTree(root); std::cout << std::endl; } int main() { TestLeftRotate1(); TestRightRotate1(); return 0; }
代碼運行效果如圖
因爲左旋轉與右旋轉 是鏡像映射的 這裏僅僅介紹左旋轉
左旋轉後
再來一個多節點的旋轉
// rbShow.cpp : 定義控制檯應用程序的入口點。 // #include "stdafx.h" #include <memory> #include <iostream> using namespace std; enum Color { red = 1, black }; struct node { Color color_; std::shared_ptr<node> left_; std::shared_ptr<node> right_; std::shared_ptr<node> parent_; int value_; node() { left_ = right_ = parent_ = nullptr; value_ = -1; color_ = black; } }; std::shared_ptr<node> nil(new node); std::shared_ptr<node> CreateNode(Color color, int i) { std::shared_ptr<node> p(new node); p->color_ = color; p->left_ = nil; p->right_ = nil; p->parent_ = nil; p->value_ = i; return p; } void RightRotate(std::shared_ptr<node>& root, std::shared_ptr<node> x) { std::shared_ptr<node> y = x->left_; x->left_ = y->right_; if (y->right_ != nil) y->right_->parent_ = x; y->parent_ = x->parent_; if (x->parent_ == nil) { root = y; } else if (x->parent_->left_ == x) { x->parent_->left_ = y; } else { x->parent_->right_ = y; } y->right_ = x; x->parent_ = y; } void LeftRotate(std::shared_ptr<node>& root, std::shared_ptr<node> x) { std::shared_ptr<node> y = x->right_; x->right_ = y->left_; if (y->left_ != nil) y->left_->parent_ = x; y->parent_ = x->parent_; if (x->parent_ == nil) { root = y; } else if (x->parent_->left_ == x) { x->parent_->left_ = y; } else { x->parent_->right_ = y; } y->left_ = x; x->parent_ = y; } void PrinTree(std::shared_ptr<node> root) { if (root == nil) { return; } std::cout << root->value_ << " "; if (root->left_ != nil) PrinTree(root->left_); if (root->right_ != nil) PrinTree(root->right_); } void TestLeftRotate2() { //測試 1 3 2 4 std::shared_ptr<node> root = CreateNode(black, 1); root->parent_ = nil; root->right_ = CreateNode(red, 3); root->right_->parent_ = root; std::shared_ptr<node> x = root->right_; std::shared_ptr<node> y = CreateNode(red, 2); x->left_ = y; y->parent_ = x; std::shared_ptr<node> z = CreateNode(red, 4); x->right_ = z; z->parent_ = x; PrinTree(root); std::cout << std::endl; LeftRotate(root, x); PrinTree(root); std::cout << std::endl; } void TestRightRotate1() { //測試 9 10 6 8 4 2 5 std::shared_ptr<node> root = CreateNode(black, 9); root->parent_ = nil; std::shared_ptr<node> a = root; std::shared_ptr<node> b = CreateNode(black, 10); a->right_ = b; b->parent_ = a; std::shared_ptr<node> c = CreateNode(black, 6); a->left_ = c; c->parent_ = a; std::shared_ptr<node> d = CreateNode(black, 8); c->right_ = d; d->parent_ = c; std::shared_ptr<node> e = CreateNode(black, 4); c->left_ = e; e->parent_ = c; std::shared_ptr<node> f = CreateNode(black, 2); e->left_ = f; f->parent_ = e; std::shared_ptr<node> g = CreateNode(black, 5); e->right_ = g; g->parent_ = e; PrinTree(root); std::cout << std::endl; RightRotate(root, c); PrinTree(root); std::cout << std::endl; } int main() { TestLeftRotate1(); std::cout << std::endl; TestRightRotate1(); return 0; }
這裏介紹右旋轉 圖示如圖
節點6進行右旋轉後