博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
说说红黑树
阅读量:6607 次
发布时间:2019-06-24

本文共 5863 字,大约阅读时间需要 19 分钟。

hot3.png

红黑树的性质:

        红黑树的每个节点(node)都有一个flag位,不是红色(Red)就是黑色(Black)。通过对任意一条从跟节点到叶子节点的简单路径的颜色加以约束,可以保证没有
一条路径会比其它路径长出2倍,这样便使得红黑树可以达到近似平衡的。
        每个node包含5个属性和所属数据,当然有些优化了的红黑树可能更为复杂,这里不讨论。
            typedef struct Node{
                struct Node* left;  //指向左子节点
                struct Node* right; //指向右子节点
                enum Color color;   //节点颜色
                int key;            //关键字
                struct Node* p;     //节点的父节点
                struct Data* data;  //节点数据,前5个为属性
            } *rb_node_ptr,rb_node;
        一颗红黑树必定满足以下5个性质:
            1.每个节点是黑色或红色;
            2.跟节点是黑色;
            3.红色节点的子节点必定为黑色;
            4.叶子节点为黑色;
            5.从一个节点出发(不包含该节点)到叶子节点的任意简单路径所经过的黑色节点数目必定一致。
        通常使用哨兵来处理红黑树的边界条件。所谓红黑树的哨兵,就是增加一个节点来收集所有指向叶子节点的普通节点的指向,这样不会影响红黑树的性质,而且可以节省空间。由于节点到叶子节点的任意简单路径所经过的黑节点数目是明确定义的,因此定义为从跟节点到叶子节点的所经过的黑节点数目,称为“黑高(black-height)。

 

红黑树数型改变时性质的维护:

        随着红黑树的树形变化,比如在add,delete等操作后,会改变当前树形。为维持红黑树的性质必需对数据节点进行调整。

节点的旋转:

        维持红黑树的性质的方法是对节点进行旋转,旋转包括左旋和右旋。旋转操作并不会改变关键字的前后顺序。个人理解这个左旋和右旋其实理解为顺时针旋转和逆时针旋转更形象。旋转涉及到两个节点x,y和三个子树alpha,gama,beta,如图所示。

添加数据:

C++代码清单:

redblacktree.h

#ifndef _REDBLACKTREE_NODE_#define _REDBLACKTREE_NODE_#include
enum Color{ RED, BLACK};struct data{ int d;};typedef struct RedBlackTreeNode{ struct data use_data; int key; struct RedBlackTreeNode* lchild; struct RedBlackTreeNode* rchild; struct RedBlackTreeNode* parent; enum Color color;}red_black_tree_node,*red_black_tree_node_ptr;class RedBlackTree{private: red_black_tree_node_ptr root; red_black_tree_node guard;public: RedBlackTree(); ~RedBlackTree();private: void init_tree(); void destroy_tree(); void red_black_tree_fixup(red_black_tree_node_ptr);public: void insert_node(red_black_tree_node&);private: red_black_tree_node_ptr get_node_ptr(red_black_tree_node&); void left_rotate(red_black_tree_node_ptr&); void right_rotate(red_black_tree_node_ptr&);};#endif //redblacktree.h

redblacktree.cc 

#include "redblacktree.h"#include 
#include
RedBlackTree::RedBlackTree(){ init_tree();}RedBlackTree::~RedBlackTree(){ destroy_tree();}void RedBlackTree::init_tree(){ this->guard.color = BLACK; this->guard.lchild = NULL; this->guard.rchild = NULL; this->guard.parent = NULL; this->guard.key = 0; this->root = get_node_ptr(this->guard);}void RedBlackTree::destroy_tree(){}red_black_tree_node_ptr RedBlackTree::get_node_ptr(red_black_tree_node& node){ return &node;}void RedBlackTree::insert_node(red_black_tree_node& node){ red_black_tree_node_ptr y_ptr = get_node_ptr(this->guard); red_black_tree_node_ptr x_ptr = this->root; while(x_ptr != get_node_ptr(this->guard)){ y_ptr = x_ptr; if(node.key <= x_ptr->key) x_ptr = x_ptr->lchild; else x_ptr = x_ptr->rchild; } node.parent = y_ptr; if(y_ptr == get_node_ptr(this->guard)){ this->root = get_node_ptr(node); } else if(node.key <= y_ptr->key){ y_ptr->lchild = get_node_ptr(node); } else{ y_ptr->rchild = get_node_ptr(node); }node.lchild = get_node_ptr(this->guard);node.rchild = get_node_ptr(this->guard);node.color = RED;red_black_tree_fixup(get_node_ptr(node));}void RedBlackTree::red_black_tree_fixup(red_black_tree_node_ptr node_ptr){ while(node_ptr->parent->color == RED){ if(node_ptr->parent == node_ptr->parent->parent->lchild){ red_black_tree_node_ptr uncle_ptr = node_ptr->parent->parent->rchild; if(uncle_ptr->color == RED){ node_ptr->parent->color = BLACK; uncle_ptr->color = BLACK; node_ptr->parent->parent->color = RED; node_ptr = node_ptr->parent->parent; } else if(node_ptr == node_ptr->parent->rchild){ node_ptr = node_ptr->parent; left_rotate(node_ptr); } node_ptr->parent->color = BLACK; node_ptr->parent->parent->color = RED; right_rotate(node_ptr->parent->parent); } else if(node_ptr->parent == node_ptr->parent->parent->rchild){ red_black_tree_node_ptr uncle_ptr = node_ptr->parent->parent->lchild; if(uncle_ptr->color == RED){ node_ptr->parent->color = BLACK; uncle_ptr->color = BLACK; node_ptr->parent->parent->color = RED; node_ptr = node_ptr->parent->parent; } else if(node_ptr == node_ptr->parent->lchild){ node_ptr = node_ptr->parent; right_rotate(node_ptr); } node_ptr->parent->color = BLACK; node_ptr->parent->parent->color = RED; left_rotate(node_ptr->parent->parent); } }this->root->color = BLACK;}void RedBlackTree::left_rotate(red_black_tree_node_ptr& node_ptr){ red_black_tree_node_ptr right_sub_node_ptr = node_ptr->rchild; node_ptr->rchild = right_sub_node_ptr->lchild; if(right_sub_node_ptr->lchild != get_node_ptr(this->guard)){ right_sub_node_ptr->lchild->parent = node_ptr; } right_sub_node_ptr->parent = node_ptr->parent; if(node_ptr->parent == get_node_ptr(this->guard)){ this->root = right_sub_node_ptr; } else if(node_ptr == node_ptr->parent->lchild){ node_ptr->parent->lchild = right_sub_node_ptr; } else{ node_ptr->parent->rchild = right_sub_node_ptr; } right_sub_node_ptr->lchild = node_ptr; node_ptr->parent = right_sub_node_ptr;}void RedBlackTree::right_rotate(red_black_tree_node_ptr& node_ptr){ red_black_tree_node_ptr left_sub_node_ptr = node_ptr->lchild; node_ptr->lchild = left_sub_node_ptr->rchild; if(left_sub_node_ptr->rchild != get_node_ptr(this->guard)){ left_sub_node_ptr->rchild->parent = node_ptr; } left_sub_node_ptr->parent = node_ptr->parent; if(node_ptr->parent == get_node_ptr(this->guard)){ this->root = left_sub_node_ptr; } else if(node_ptr == node_ptr->parent->rchild){ node_ptr->parent->rchild = left_sub_node_ptr; } else{ node_ptr->parent->lchild = left_sub_node_ptr; } left_sub_node_ptr->rchild = node_ptr; node_ptr->parent = left_sub_node_ptr;}

main.cc

#include "redblacktree.h"int main(){  RedBlackTree tree;  red_black_tree_node node1;  node1.key = 11;  tree.insert_node(node1);    red_black_tree_node node2;  node2.key = 12;  tree.insert_node(node2);  return 0;}

 

搞清楚节点和节点指针的关系:

转载于:https://my.oschina.net/u/2309100/blog/832916

你可能感兴趣的文章
HTTP要被抛弃? 亚洲诚信携手宝塔开启HTTPS加密快速通道
查看>>
Chrome: 完全移除对WoSign和StartCom证书的信任
查看>>
RecyclerView侧滑删除功能
查看>>
记一个hystrix异常
查看>>
9.02-Spring IOC 容器中Bean的生命周期
查看>>
6.6 tar打包
查看>>
Spring MVC核心技术
查看>>
TCP协议如何保证传输的可靠性
查看>>
Spring Cloud云架构 - SSO单点登录之OAuth2.0 登出流程(3)
查看>>
编程之美 测试赛 石头剪刀布
查看>>
签名问题
查看>>
软件开发各阶段交付物列表
查看>>
2018-05-24 Linux学习
查看>>
ntp服务器的搭建
查看>>
我的友情链接
查看>>
sysstat 安装
查看>>
六、nginx搭建织梦DedeCms网站
查看>>
Tair学习小记
查看>>
网卡绑定(服务器&&交换机),缓存服务器Squid架构配置
查看>>
web网站加速之CDN(Content Delivery Network)技术原理
查看>>