算法導論 紅黑樹 學習 旋轉(二)圖文

學習算法 仍是建議看看算法導論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進行右旋轉後

相關文章
相關標籤/搜索