算法导论 红黑树 学习 旋转(二)图文

学习算法 还是建议看看算法导论

算法导论第三版 如果不看数学推导 仅看伪代码 难度还是适中

本系列只是记录我的学习心得 和伪代码转化代码的过程

深入学习 还是建议大家看看算法书籍 教程更加系统。

 

本文参考算法导论第13章节 红黑树

代码由本人写成

转载请标明出处

 

 

红黑树是一个带颜色的二叉树

有以下5点性能

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进行右旋转后

 

转载于:https://www.cnblogs.com/itdef/p/6395240.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
信息数据从传统到当代,是一直在变革当中,突如其来的互联网让传统的信息管理看到了革命性的曙光,因为传统信息管理从时效性,还是安全性,还是可操作性等各个方面来讲,遇到了互联网时代才发现能补上自古以来的短板,有效的提升管理的效率和业务水平。传统的管理模式,时间越久管理的内容越多,也需要更多的人来对数据进行整理,并且数据的汇总查询方面效率也是极其的低下,并且数据安全方面永远不会保证安全性能。结合数据内容管理的种种缺点,在互联网时代都可以得到有效的补充。结合先进的互联网技术,开发符合需求的软件,让数据内容管理不管是从录入的及时性,查看的及时性还是汇总分析的及时性,都能让正确率达到最高,管理更加的科学和便捷。本次开发的高校科研信息管理系统实现了操作日志管理、字典管理、反馈管理、公告管理、科研成果管理、科研项目管理、通知管理、学术活动管理、学院部门管理、科研人员管理、管理员管理等功能。系统用到了关系型数据库中王者MySql作为系统的数据库,有效的对数据进行安全的存储,有效的备份,对数据可靠性方面得到了保证。并且程序也具备程序需求的所有功能,使得操作性还是安全性都大大提高,让高校科研信息管理系统更能从理念走到现实,确确实实的让人们提升信息处理效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值