算法学习---红黑树
来源:互联网 发布:mac 如何切换中英文 编辑:程序博客网 时间:2024/06/06 01:20
1、红黑树是二叉收索树的一种,可以保证在最坏情况系基本动态集合操作的时间复杂度为O(lgn)。本质是让树尽量均衡。
红黑树的定义(红黑树是在二叉收索树的基础上加上了下面的条件):
(1)每个节点或是红色的,或是黑色的。
(2)根节点和叶结点是黑色的。(红黑树中将NIL结点定义为也节点,称为外部结点;把带关键字的结点视为树的内部结点)。
(3)如果一个结点是红色的,则它的两个子结点是黑色的(父结点也是黑色的)。
(4)对每个结点,从该结点到其所有后代叶结点的简单路径上,均包括相同数目的黑色结点。(不含该结点的黑结点的数目称为黑高)
2、引理:一颗有n个内部结点的红黑树的高度至多为2lg(n+1)。
证明:
3、代码的实现:
R_B_tree.h
#ifndef __RedBlackTree#define __RedBlackTree#include<iostream>#include<queue>using namespace std;typedef enum NodeColor{ RED, BLACK}NodeColor;typedef struct Node{ NodeColor color; int key; Node *left; Node *right; Node *parent;}Node;class RedBlackTree{ public: RedBlackTree(); //空树 ~RedBlackTree(); Node *Search(int key); //根据关键字key从根部查询节点,将节点返回 Node *Minimum(Node *x); //以x为根的红黑树的最小值 Node *Maximum(Node *x); //以x为根的红黑树的最大值 Node *Successor(Node *node); //后继 Node *Predecessor(Node *node); //前驱 void InsertNode(Node *node); //将node结点插入root树 void InorderTreeWalk(Node *x); //中序遍历 void DelleteNode(Node *z); //删除节点private: void LeftRotate(Node *x); //按x点左旋 void RightRotate(Node *y); //按y点右旋 void InsertFixup(Node *z); //插入节点后从新着色 void Transplant(Node *u,Node *v); //用v节点为根的子树替换u节点为根的子树 void DelleteFixup(Node *z); //删除节点之后重新着色private: Node leaf; //哨兵结点public: Node *root; //树根 };#else#pragma message("--RedBlackTree已编译。") #endif
R_B_tree.cpp
#include"R_B_tree.h"RedBlackTree::RedBlackTree(){ this->leaf.color=BLACK; this->leaf.key=0; this->leaf.left=NULL; this->leaf.parent=NULL; this->leaf.right=NULL; root=&leaf; //空红黑树}RedBlackTree::~RedBlackTree(){}Node * RedBlackTree::Minimum(Node *x){ if( x==&leaf ){ //x为叶子 return x; } while( x->left != &leaf ){ x=x->left; } return x; //最小}Node * RedBlackTree::Maximum(Node *x){ if( x==&leaf ){ //x为叶子 return x; } while( x->right != &leaf ){ x=x->right; } return x; //最大} Node * RedBlackTree::Successor(Node *node){ if(node==&leaf) return node; return Minimum(node->right);}Node * RedBlackTree::Predecessor(Node *node){ if(node==&leaf) return node; return Maximum(node->left);}Node * RedBlackTree::Search(int key){ Node *x; x=root; while( x != &leaf && x->key != key ){ if( x->key > key )x=x->left; else if(x->key < key) x=x->right; } return x; //查询失败是返回叶子结点}void RedBlackTree::LeftRotate(Node *x){ Node *y; y=x->right; x->right=y->left; if( y->left != &leaf ){ y->left->parent=x; } y->parent=x->parent; if( x->parent == &leaf ){ //x为根 root=y; }else{ if( x == x->parent->left ){ //x为父结点的左孩子 x->parent->left=y; }else{ //x为右孩子 x->parent->right=y; } } y->left=x; x->parent=y;}void RedBlackTree::RightRotate(Node *y){ Node *x; x=y->left; y->left=x->right; if( x->right != &leaf){ x->right->parent=y; } x->parent=y->parent; if( y->parent == &leaf ){ root=x; }else{ if( y->parent->left==y ){ //左边第一个结点 y->parent->left=x; }else{ y->parent->right=x; //右边第一个结点 } } x->right=y; y->parent=x;}void RedBlackTree::InsertFixup(Node *z){ Node *y; while( z->parent->color == RED ){ if( z->parent==z->parent->parent->left ){ y=z->parent->parent->right; //叔结点 if( y->color==RED ){ //情况一 z->parent->color=BLACK; y->color=BLACK; z->parent->parent->color=RED; z=z->parent->parent; }else{ if( z->parent->right == z ){ //情况二 右孩子 z=z->parent; this->LeftRotate(z); } z->parent->color=BLACK; //情况三 左孩子 z->parent->parent->color=RED; this->RightRotate(z->parent->parent); } }else{ y=z->parent->parent->left; //叔结点 if( y->color==RED ){ //情况一 z->parent->color=BLACK; y->color=BLACK; z->parent->parent->color=RED; z=z->parent->parent; }else{ if( z->parent->left == z ){ //情况二 左孩子 z=z->parent; this->RightRotate(z); } z->parent->color=BLACK; //情况三 左孩子 z->parent->parent->color=RED; this->LeftRotate(z->parent->parent); } } } root->color=BLACK;}void RedBlackTree::InsertNode(Node *node){ Node *y,*x; y=&leaf;x=root; while( x!=&leaf ){ y=x; if( node->key < x->key ){ x=x->left; }else{ x=x->right; } } node->parent=y; if( y == &leaf ){ root=node; }else{ if(node->key<y->key){ y->left=node; }else{ y->right=node; } } node->left=&leaf; node->right=&leaf; node->color=RED; this->InsertFixup(node);}void RedBlackTree::InorderTreeWalk(Node *x){ if( x != &leaf ){ InorderTreeWalk(x->left); cout<<"key="<<x->key; if( x->color==RED ){ cout<<" RED"; }else{ cout<<" BLACK"; } cout<<" parent_ket="<<x->parent->key<<" key_left="<<x->left->key<<" key_right="<<x->right->key<<endl; InorderTreeWalk(x->right); }}void RedBlackTree::Transplant(Node *u,Node *v){ if(u->parent==&leaf){ root=v; }else{ if( u==u->parent->left ){ u->parent->left=v; }else{ u->parent->right=v; } } v->parent=u->parent;}void RedBlackTree::DelleteFixup(Node *z){ Node *w; while( z!=root && z->color == BLACK ){ if( z==z->parent->left ){ w=z->parent->right; if( w->color==RED ){ w->color=BLACK; z->parent->color=RED; this->LeftRotate(z->parent); w=z->parent->right; } if( w->left->color==BLACK && w->right->color==BLACK){ w->color=RED; z=z->parent; }else{ if( w->right->color==BLACK ){ w->left->color=BLACK; w->color=RED; this->RightRotate(w); w=z->parent->right; } w->color=z->parent->color; z->parent->color=BLACK; w->right->color=BLACK; this->LeftRotate(z->parent); z=root; } }else{ w=z->parent->left; if( w->color==RED ){ w->color=BLACK; z->parent->color=RED; this->RightRotate(z->parent); w=z->parent->left; } if( w->left->color==BLACK && w->right->color==BLACK){ w->color=RED; z=z->parent; }else{ if( w->left->color==BLACK ){ w->right->color=BLACK; w->color=RED; this->LeftRotate(w); w=z->parent->left; } w->color=z->parent->color; z->parent->color=BLACK; w->left->color=BLACK; this->RightRotate(z->parent); z=root; } } } z->color=BLACK;}void RedBlackTree::DelleteNode(Node *z){ Node *x,*y; NodeColor y_original_color; y=z; y_original_color=y->color; if( z->left==&leaf ){ x=z->right; Transplant(z,z->right); }else{ if(z->right==&leaf){ x=z->left; Transplant(z,z->right); }else{ y=Minimum(z->right); y_original_color=y->color; x=y->right; if( y->parent==z ){ x->parent=y; }else{ Transplant(y,y->right); y->right=z->right; y->right->parent=y; } Transplant(z,y); y->left=z->left; y->left->parent=y; y->color=z->color; } } if(y_original_color==BLACK){ DelleteFixup(x); } delete z;}
main.cpp
#include<ctime>#include"R_B_tree.h"int main(){ Node *newNode; RedBlackTree RB; int i=4; srand(time(0)); int kk; while(i<11){ //kk=rand()%10+5; newNode=new Node; newNode->color=RED; newNode->key=i; newNode->left=NULL; newNode->right=NULL; newNode->parent=NULL; RB.InsertNode(newNode); i++; } cout<<"创建的红黑树"<<endl; RB.InorderTreeWalk((RB.root)); if( RB.Search(RB.root->key)->key==0 ){ cout<<"查询的结点不存在!"<<endl; }else{ cout<<"查询的根节点结点为 "<<RB.Search(RB.root->key)->key<<endl; } RB.DelleteNode((RB.root)); cout<<"删除根节点之后的红黑树 "<<endl; RB.InorderTreeWalk((RB.root)); if( RB.Search(RB.root->key)->key==0 ){ cout<<"查询的结点不存在!"<<endl; }else{ cout<<"查询的根节点结点为 "<<RB.Search(RB.root->key)->key<<endl; } int asd; cin>>asd; return 0;}
运行截图:
4、关于红黑树删除的一些说明
红黑树所有操作里,结点的删除是最复杂的,相关的删除的操作的详细过程可以看http://www.cnblogs.com/Anker/archive/2013/01/30/2882773.html博客,写的不错,看过之后容易明白。在这里我在添加关于4种情况的实例,从而可以更好理解红黑树删除时的四种情况。
0 0
- 算法学习----红黑树
- 算法学习---红黑树
- 算法学习_红黑树
- 算法学习
- 算法学习
- 算法 学习
- 算法学习
- 算法学习
- 学习算法
- 算法学习
- 算法学习
- 算法 学习
- 算法学习
- 学习算法
- 算法学习
- 算法学习
- 算法学习
- 算法学习
- Android界面切换
- Java应用程序高CPU故障诊断(troubleshooting)思路
- 详解js闭包
- Tomcat启动报错Cannot connect to VM
- 二叉查找树
- 算法学习---红黑树
- 【操作系统】进程调度及其算法
- Thread.currentThread().getContextClassLoader()
- hihocoder#1055之刷油漆
- 【.net基础】--.NET、winform、Asp.Net区别
- H5,Audio音乐播放器(移动版)
- 企业实训收获之--web前端设计
- HDU5233 Gunner II 离散化的各种方法
- P81