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

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

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

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

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

本文参考算法导论第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进行右旋转后

时间: 2024-12-25 10:18:23

算法导论 红黑树 学习 旋转(二)的相关文章

算法导论 红黑树 学习 删除(四)

版权声明:本文为博主原创文章,未经博主允许不得转载.技术博客 http://blog.csdn.net/stecdeng 技术交流群 群号码:324164944 欢迎c c++ windows驱动爱好者 服务器程序员沟通交流 学习算法 还是建议看看算法导论 算法导论第三版 如果不看数学推导 仅看伪代码 难度还是适中 本系列只是记录我的学习心得 和伪代码转化代码的过程 深入学习 还是建议大家看看算法书籍 教程更加系统. 本文参考算法导论第13章节 红黑树 代码由本人写成 转载请标明出处 先看看不做

算法导论—红黑树

华电北风吹 天津大学认知计算与应用重点实验室 日期:2015/9/9 红黑树是对二叉树的一种平衡扩展.红黑树采用开放的数据扩张策略,并且对于诸如插入.查询,删除有Θ(lg n)的时间复杂度,因此也是一种应用比较广泛的数据结构. 一.红黑树的节点 节点属性:关键字key,节点颜色,左孩子指针,右孩子指针,父节点指针,卫星数据. 虚拟节点-NIL:对于红黑树中所有节点如果没有父节点或者缺少某个子节点,则把对应的指针指向同一个NIL. 二.红黑树的性质 1.每个节点的颜色是红色或黑色. 2.根节点是黑

算法导论-------------红黑树

红黑树是一种二叉查找树,但在每个结点上增加了一个存储位表示结点的颜色,可以是RED或者BLACK.通过对任何一条从根到叶子的路径上各个着色方式的限制,红黑树确保没有一条路径会比其他路径长出两倍,因而是接近平衡的.本章主要介绍了红黑树的性质.左右旋转.插入和删除.重点分析了在红黑树中插入和删除元素的过程,分情况进行详细讨论.一棵高度为h的二叉查找树可以实现任何一种基本的动态集合操作,如SEARCH.PREDECESSOR.SUCCESSOR.MIMMUM.MAXMUM.INSERT.DELETE等

[[算法导论]红黑树速记

红黑树的性质: 1.每个结点要么是红色要么是黑色的. 2.根结点是黑色的. 3.所有叶结点(nil)是黑色的. 4.每个红色结点的两个孩子都是黑色的. 5.每个结点到其后代叶结点的简单路径上均包含相同数目的黑色结点. INSERT操作按二叉搜索树的方法插入新结点. INSERT-FIXUP(三种情况): 插入后新结点(z)为红色,当z.p==z.p.p.left时. 循环条件:父结点为红色. 情况1:叔结点(z.p.p.right)为红色. 父结点和叔结点改为黑色,祖父结点改为红色并成为新的z结

算法导论 红黑树 实现

由于红黑树的删除用到了二叉树的一些函数 所以我们从二叉树讲起 二叉树 不带颜色的红黑树 看看两张画的有点丑的图 如图 一个节点 记录一个数值 同时还有两个指向该节点两个儿子的标识 儿子有两个 左儿子和右儿子 图中就有两个二叉树示例 一个仅有右儿子  一个左右儿子均有 C语言中或者C++语言中我们这样定义二叉树结构 struct node { std::shared_ptr<node> left_; //智能指针 std::shared_ptr<node> right_; int v

算法导论 红黑树 实现(一)

首先实现插入 左旋转 右旋转 并测试暂时未考虑颜色转换 // rbTreeTest.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <memory> #include <iostream> using namespace std; enum Color { red = 1, black }; struct node { Color color_; std::shared_ptr<node> l

[算法导论]红黑树插入实现 @ Python

直接上代码: class RBTree: def __init__(self): self.nil = RBTreeNode(0) self.root = self.nil class RBTreeNode: def __init__(self, x): self.key = x self.left = None self.right = None self.parent = None self.color = 'black' class Solution: def InorderTreeWal

算法之红黑树

红黑树(一) 原理和算法详细介 1 R-B Tree简介 R-B Tree,全称是Red-Black Tree,又称为"红黑树",它一种特殊的二叉查找树.红黑树的每个节点上都有存储位表示节点的颜色,可以是红(Red)或黑(Black). 红黑树的特性:(1)每个节点或者是黑色,或者是红色.(2)根节点是黑色.(3)每个叶子节点(NIL)是黑色. [注意:这里叶子节点,是指为空(NIL或NULL)的叶子节点!](4)如果一个节点是红色的,则它的子节点必须是黑色的.(5)从一个节点到该节点

算法:红黑树

算法:红黑树 红黑树介绍 红黑树(英语:Red–black tree)是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组.它是在1972年由鲁道夫·贝尔发明的,他称之为"对称二叉B树",它现代的名字是在Leo J. Guibas和Robert Sedgewick于1978年写的一篇论文中获得的. 红黑树本质上是一种二叉查找树,但它在二叉查找树的基础上额外添加了一个标记(颜色),同时具有一定的规则.这些规则使红黑树保证了一种平衡,插入.删除.查找的最坏时