红黑树源码及错误解析

 

/* 作者:田帅

学校:**大学

版本:红黑树初始版本

*/

#include"stdio.h"

#include"malloc.h"

#define MIN -99999999 //不要加等号

#define MAX 99999999

struct node

{

long key;

char color;

struct node *p;

struct node *leftChild;

struct node *rightChild;

};

node *nil,*root;//创建根节点和叶子节点

int printnode=0;

node *CreateNode(int key);

void RB_insert_fixUp(node *T,node *z);

void nil_create();//叶子节点创建

void RB_insert(node *T,node *z);//弄算法导论上非递归的吧

void left_rotate(node *T,node *z);//向左旋转

void right_rotate(node *T,node *z);

void PrintRBTree(node *T);//输出树

void nil_create()//叶子节点创建

{

nil=(node *)malloc(sizeof(node));

root=(node *)malloc(sizeof(node));

nil->key=MIN;

nil->color='B';

//nil->p=NULL;//这里注意

nil->leftChild=nil;

nil->rightChild=nil;

root=nil;

}

node *CreateNode(int key)

{

node *x = (node *)malloc(sizeof(node));

x->color ='R';

x->key = key;

x->leftChild = nil;

x->rightChild = nil;

x->p = NULL;

return x;

}

void RB_insert(node *T,node *z)//弄算法导论上非递归的吧

{

node *x,*y;//y用来记录父节点

x=root;//这里应该是 根节点 跟形式参数重复 会造成错误

y=nil;

while(x!=nil)//x为要插入的位置de父节点 y为x的父节点

{

y=x;

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

x=x->leftChild;

else

x=x->rightChild;

}

z->p=y;

if(y==nil)//初始化 插入到空树种

root=z;

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

y->leftChild=z;

else

y->rightChild=z;

z->leftChild=nil;

z->rightChild=nil;

z->color='R';

RB_insert_fixUp(T,z);

}

void RB_insert_fixUp(node *T,node *z)

{

node *y;

while(z->p->color=='R')//插入节点 是红节点 如果父节点也是红节点 则需要调整

{

if(z->p==z->p->p->leftChild)//插入的节点的父节点 是祖父节点的左孩子

{

y=z->p->p->rightChild;//祖父节点的右孩子

if(y->color=='R')//二叔是 红色的O(∩_∩)O哈哈~

{

z->p->color='B';

y->color='B';

z->p->p->color='R';

z=z->p->p;

}

else

{//这个地方一定要加上 {

if(z==z->p->rightChild)//二叔是黑色 且 要插入的节点是右孩子

{

z=z->p;

left_rotate(T,z);

}

z->p->color='B';//二叔是黑色 且要插入的节点是左孩子

z->p->p->color='R';

// z->p->p->color='R'; //???????????????????????????

right_rotate(T,z->p->p);

}

}

else//插入的节点的父节点 是祖父节点的右孩子

{

y=z->p->p->leftChild;//祖父节点的左孩子

if(y->color=='R')//二叔是 红色的O(∩_∩)O哈哈~

{

z->p->color='B';

y->color='B';

z->p->p->color='R';

z=z->p->p;//???????

}

else

{

if(z==z->p->leftChild)//二叔是黑色 且 要插入的节点是左孩子

{

z=z->p;

right_rotate(T,z);

}

z->p->color='B';//二叔是黑色 且要插入的节点是右孩子

z->p->p->color='R';

left_rotate(T,z->p->p);

}

}

}

root->color='B';//这里不要落下!!!

}

void left_rotate(node *T,node *z)//向左旋转

{

node *y;

y=z->rightChild;//让y 为要旋转的节点的右子树

z->rightChild=y->leftChild;

if(y->leftChild!=nil)

y->leftChild->p=z;

y->p=z->p;//将要旋转节点切下

if(z->p==nil)

root=y;

else if(z==z->p->leftChild)//要旋转节点是 其父节点左孩子

z->p->leftChild=y;

else//要旋转节点是 其父节点右孩子

z->p->rightChild=y;

y->leftChild=z;//将要旋转节点挂到 代替它的孩子的左子树上

z->p=y;

}

void right_rotate(node *T,node *z)

{

node *y;

y=z->leftChild;//让y 为要旋转的节点的左子树

z->leftChild=y->rightChild;

if(y->rightChild!=nil)

y->rightChild->p=z;

y->p=z->p;//将要旋转节点切下

if(z->p==nil)

root=y;

else if(z==z->p->leftChild)//要旋转节点是 其父节点左孩子

z->p->leftChild=y;

else//要旋转节点是 其父节点右孩子

z->p->rightChild=y;

y->rightChild=z;//将要旋转节点挂到 代替它的孩子的左子树上

z->p=y;

}

void PrintRBTree(node *T)

{

int i;

if(T != nil)

{

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

printf(" ");

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

if(T->color == 'B')

printf("B,\n");

else

printf("R,\n");

printnode++;

PrintRBTree(T->leftChild);

PrintRBTree(T->rightChild);

printnode--;

for(int j = 0; j <= printnode;j++)

printf(" ");

printf("),\n");

}

else

{

for(int i = 0; i <= printnode;i++)

printf(" ");

printf("Nil,\n");

}

}

void INORDER_TREE_WALK(struct node* x) //中根遍历

{

//printf("%ld %c ",x->key,x->color); //debug 先根遍历

if(x->leftChild!=nil)

INORDER_TREE_WALK(x->leftChild);

printf("%ld %c ",x->key,x->color);

if(x->rightChild!=nil)

INORDER_TREE_WALK(x->rightChild);

}

int main()

{ //long a[11]={4,1,3,2,16,9,10,14,8,7};

//long a[10]={10,9,8,7,6,5,4,3,2,1};

// long a[10]={1,2,3,4,5,6,7,8,9,10};

// long a[]={1,2,3,4,5,6,7,8,9,10};//这个可以

long a[]={4,1,3,2,16,9,10,14,8,7};//这个不可以

node *z[11];

nil_create();

// nil=(node *)malloc(sizeof(node));

// nil=nil_create();

printf(" 1111111");

for(int j = 0; j <10; j++)

{

printf(" 222222 ");

z[j]=CreateNode(a[j]);

RB_insert(root,z[j]);

}

printf(" 222222 ");

INORDER_TREE_WALK(root);

// PrintRBTree(root);

return 0;

}

出现的错误及调试方法:

总是到insert_fix_up时候出现错误;原因是 第三种情况 要写在 if(y.color=='R') else{ if() ; ********} 不要忘记在else 之后加上 大括号

原文地址:https://www.cnblogs.com/secbook/p/2655086.html