红黑树插入

#include<stdio.h>
#define Red 0
#define Black 1 
#define N 100   //树的最大规模

typedef struct RBTNode
{
 int key;
 int color;//Black:1,Red:0
    struct RBTNode *left,*right,*parent;
}RBTNode,*RBTree;

RBTNode *nil,*Root,*Node[N];

void Init()       //构造叶子结点
{
 nil->color=Black;
 nil->left=Root;
 nil->right=Root;
 nil->key=-1;
 Root=nil;
}

void Creat(RBTNode *T)         //构造生成的结点

 T->color=Red;
 T->key=-1;
 T->left=T;
 T->right=T;
 T->parent=T;
}


void Left_Rotate(RBTree &T,RBTNode *x)    //左旋
{
 RBTNode *y;
 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==x->parent->left)
  x->parent->left=y;
 else x->parent->right=y;
 y->left=x;
 x->parent=y;
}


void Right_Rotate(RBTree &T,RBTNode *x)    //右旋
{
   RBTNode *y;
   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==x->parent->left)
    x->parent->left=y;
   else x->parent->right=y;
   y->right=x;
   x->parent=y;
}


void RB_Insert_Fixup(RBTree &T,RBTNode *z)  //调整插入结点
{
 RBTNode *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==z->parent->right)
    {
     z=z->parent;                                         
     Left_Rotate(T,z);    
    }
    z->parent->color=Black;                                   
    z->parent->parent->color=Red;
    Right_Rotate(T,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==z->parent->left)
    {
     z=z->parent;                                         
     Right_Rotate(T,z);    
    }
    z->parent->color=Black;                                   
    z->parent->parent->color=Red;
    Left_Rotate(T,z->parent->parent);
   }
  }
 }
 Root->color=Black;
}

 

void RB_Insert(RBTree &T,RBTNode *z)   //插入结点
{
 RBTNode *x,*y;
 y=nil;
 x=Root;
 while(x!=nil)
 {
  y=x;
  if(z->key<x->key)
   x=x->left;
  else x=x->right;
 }
 z->parent=y;
 if(y==nil)
  Root=z;
 else if(z->key < y->key)
  y->left=z;
 else y->right=z;
 z->left=nil;
 z->right=nil;
 z->color=Red;
 RB_Insert_Fixup(T,z);
}

void RB_Mid_Visit(RBTNode *T,int &m)   //中序遍历
{
 if(T!=nil)
 {
  RB_Mid_Visit(T->left,m);//递归遍历左子树
  printf("%d/t",T->key);
  if(T->color==1)
   printf("Black/n");
  else
   printf("Red/n");
  m++;
  RB_Mid_Visit(T->right,m);//递归遍历右子树
 }
}

void main()

 int i,M;
 nil=new RBTNode;
 Init();
 printf("输入不超过%d的树的规模:/n",N);
    scanf("%d",&M);
 printf("/n**************************************/n");
    printf("输入各结点的关键字:/n");
 for(i=0;i<M;i++)
 {
  Node[i]=new RBTNode;
  Creat(Node[i]);
  scanf("%d",&Node[i]->key);
  RB_Insert(Root,Node[i]);
 }
 printf("/n**************************************/n");
    printf("该树为:/n");
 i=0;
 RB_Mid_Visit(Root,i);
 printf("/n**************************************/n");
 RBTNode *z;
 z=new RBTNode;
 Node[i]=new RBTNode;
 Creat(z);
 printf("插入结点:/n");
 scanf("%d",&z->key);
 RB_Insert(Root,z);
 printf("/n**************************************/n"); 
 printf("最终树为:/n");
 i=0;
 RB_Mid_Visit(Root,i);
}

 

 

 

 

 

附:

 

 

 

红黑树插入算法

需求分析

实现对红黑树的插入结点操作。

算法设计

² 设计思想

算法使用的数据结构:

结点的类型为结构,成员变量为颜色color,关键字key,父结点 *parent,左右孩子结点 *left,  *right。定义如下:

typedef struct RBTNode

{

int key;

int color;

 struct   RBTNode *left,*right,*parent;

}RBTNode,*RBTree;

算法基本思想:

利用插入算法个构建红黑树,每插入一个节点就调用调整算法,使插入的结点保持红黑树的性质。最终的插入操作即是在初始化后的红黑树上再插入一个结点。

² 概要设计

每个函数的说明:

(1) void Init( );

     构造并初始化叶子结点

(2) void Creat(RBTNode *T);

     构造并初始化新生成结点

(3) void Left_Rotate(RBTree &T,RBTNode *x)  

以x到y之间的链为支轴进行左旋操作

(4) void Right_Rotate(RBTree &T,RBTNode *x);

以x到y之间的链为支轴进行右旋操作

  (5)void RB_Insert_Fixup(RBTree &T,RBTNode *z);

对新插入的结点z进行颜色与位置的调整,使调整后的树满足红黑性质

  (6)void RB_Insert(RBTree &T,RBTNode *z);

在树T中插入新结点z,再调用RBInsertFixup算法对树进行调整,以保持树的红黑性质

  (7)void RB_Mid_Visit(RBTNode *T,int &m)

    中序遍历树T并按关键字大小顺序输出各结点的关键字及颜色                                

 

² 详细设计

主要算法思想及描述:

#include<stdio.h>

#define Red 0

#define Black 1  

#define N 100 

#define black 0  //0代表黑色

#define red 1    //1代表红色

#define MAX 100  //树的最大规模

 

typedef struct RBTNode

{

int key;

int color;//Black:1,Red:0

    struct RBTNode *left,*right,*parent;

}RBTNode,*RBTree;

 

RBTNode *nil,*Root,*Node[N];

 

void Init();//初始化叶子结点

void Initialize(RBTNode *T);//初始化新生成结点

void Left_Rotate(RBTree &T,RBTNode *x);//左旋

   void Right_Rotate(RBTree &T,RBTNode *x);//右旋

void RB_Insert(RBTree &T,RBTNode *z);//插入结点

void RB_Insert_Fixup(RBTree &T,RBTNode *z);//调整结点算法

void RB_Mid_Visit(RBTNode *T,int &m)//中序遍历树

 

 

 

(1)main( )执行各种初始化工作,并对每个新生成结点调用插入算法,生成红黑树,之后调用中序遍历算法输出各个内结点,然后完成插入操作。设计如下:

 

void main()

{

int i,M;

nil=new RBTNode;

Init();

printf("输入不超过%d的树的规模:/n",N);

    scanf("%d",&M);

printf("/n**************************************/n");

    printf("输入各结点的关键字:/n");

for(i=0;i<M;i++)

{

Node[i]=new RBTNode;

Creat(Node[i]);

scanf("%d",&Node[i]->key);

RB_Insert(Root,Node[i]);

}

printf("/n**************************************/n");

    printf("该树为:/n");

i=0;

RB_Mid_Visit(Root,i);

printf("/n**************************************/n");

RBTNode *z;

z=new RBTNode;

Node[i]=new RBTNode;

Creat(z);

printf("插入结点:/n");

scanf("%d",&z->key);

RB_Insert(Root,z);

printf("/n**************************************/n");

printf("最终树为:/n");

i=0;

RB_Mid_Visit(Root,i);

}

(2)函数Init()执行初始化叶子结点的任务,叶子结点的颜色为黑色,左右孩子均为根结点。初始根指向叶子结点,即为空树。设计如下:

 

void Init()       //构造叶子结点

{

nil->color=Black;

nil->left=Root;

nil->right=Root;

nil->key=-1;

Root=nil;

}

(3)函数Initialize(RBTNode *T)对新生成的结点进行初始化,结点颜色为红色,以保证插入时不改变黑高,结点的关键字为-1,左右孩子均指向自身。设计如下:

 

void Creat(RBTNode *T)         //构造生成的结点

{

T->color=Red;

T->key=-1;

T->left=T;

T->right=T;

T->parent=T;

}

 

(4)函数void Left_Rotate(RBTree &T,RBTNode *x)对结点x执行左旋操作,设计如下:

 

void Left_Rotate(RBTree &T,RBTNode *x)    //左旋

{

RBTNode *y;

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==x->parent->left)

x->parent->left=y;

else x->parent->right=y;

y->left=x;

x->parent=y;

}

 

(5)函数void Right_Rotate(RBTree &T,RBTNode *x)对结点x执行左旋操作。设计如下:

 

void Right_Rotate(RBTree &T,RBTNode *x)    //右旋

{

   RBTNode *y;

   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==x->parent->left)

   x->parent->left=y;

   else x->parent->right=y;

   y->right=x;

   x->parent=y;

}

(6)函数void RB_Insert_Fixup(RBTree &T,RBTNode *z)对插入结点z后的树进行颜色与位置的调整,使新得到的树仍是一棵红黑树。设计如下:

void RB_Insert_Fixup(RBTree &T,RBTNode *z)  //调整插入结点

{

RBTNode *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==z->parent->right)

{

z=z->parent;                                          

Left_Rotate(T,z);

}

z->parent->color=Black;                                    

z->parent->parent->color=Red;

Right_Rotate(T,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==z->parent->left)

z=z->parent;                                          

Right_Rotate(T,z);

}

z->parent->color=Black;                                    

z->parent->parent->color=Red;

Left_Rotate(T,z->parent->parent);

}

}

}

Root->color=Black;

}

(7)函数void RB_Insert(RBTree &T,RBTNode *z)是树T中插入结点z,并调用结点调整函数void RB_Insert_Fixup(RBTree &T,RBTNode *z)调整插入结点后的树中结点的位置与颜色,使之保持红黑树的性质设计如下:

 

void RB_Insert(RBTree &T,RBTNode *z)   //插入结点

{

RBTNode *x,*y;

y=nil;

x=Root;

while(x!=nil)

{

y=x;

if(z->key<x->key)

x=x->left;

else x=x->right;

}

z->parent=y;

if(y==nil)

Root=z;

else if(z->key < y->key)

y->left=z;

else y->right=z;

z->left=nil;

z->right=nil;

z->color=Red;

RB_Insert_Fixup(T,z);

}

(8)函数void RB_Mid_Visit(RBTNode *T,int &m)对红黑树进行中序遍历,按关键字的大小顺序输出各个结点的值与颜色。设计如下:

 

void RB_Mid_Visit(RBTNode *T,int &m)   //中序遍历

{

if(T!=nil)

{

RB_Mid_Visit(T->left,m);//递归遍历左子树

printf("%d/t",T->key);

if(T->color==1) 

printf("Black/n");

else 

printf("Red/n");

m++;

RB_Mid_Visit(T->right,m);//递归遍历右子树

}

}

测试数据及结果

测试数据:

Ø  树的规模:5

    原树结点关键字:23,2,56,89,3

    插入结点关键字:34

结果如下:

输入不超过100的树的规模:

5

 

**************************************

输入各结点的关键字:

23

2

56

89

3

 

**************************************

该树为:

2       Black

3       Red

23      Black

56      Black

89      Red

 

**************************************

插入结点:

45

 

**************************************

最终树为:

2       Black

3       Red

23      Black

45      Red

56      Black

89      Red

Press any key to continue

Ø  树的规模:10

    原树结点关键字:23,11,5,34,7,38,6,9,26,98

    插入结点关键字:34

结果如下:

输入不超过100的树的规模:

10

 

**************************************

输入各结点的关键字:

23

11

5

34

7

38

6

9

26

98

 

**************************************

该树为:

5       Black

6       Red

7       Black

9       Red

11      Black

23      Black

26      Red

34      Red

38      Black

98      Red

 

**************************************

插入结点:

10

 

**************************************

最终树为:

5       Black

6       Red

7       Red

9       Black

10      Red

11      Black

23      Black

26      Red

34      Red

38      Black

98      Red

Press any key to continue

 

 

时间及空间性能分析

时间分析:函数RBInsertFixup(RBTree &T,RBTNode *z)的运行时间为O(lgn)

函数RBInsert(RBNode *T,RBNode *z)的运行时间为O(lgn)

   因此对于n个结点的红黑树,总的时间复杂度为O(nlgn)

  空间复杂度为O(n)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值