算法————笔试内容--->红黑树(二)

本部分主要是进行红黑树插入操作的代码实现与部分图片解释:

上一部分解释一些关于红黑树的插入操作和旋转染色的操作,忘记了的小伙伴么可以再温习一下微笑,

下面开始coding。。。。

左旋操作--->代码如下:

void left_rotate(node *tree_root,node *z){
	node * y ;
	//将Z的右子树赋值给y由y来管理
	y = z->right;
	//将z的右侧指向y的侧树的节点
	z->right = y->left;
	if(y->left != NULL){//如果y的左子树不为空,那么将y的左子树的父指针指向z
		y->left->parent = z;
	}
	//将y的父指针指向原来z的父指针指向的地方
	y->parent = z->parent;
	//如果z的父指针指的是空
	if(z->parent == NULL){
		tree_root = y;//那么z为树的根,更新一下树根的指针
	}else if(z == z->parent->left){//如果z不是树根,是一个节点的左子树
		z->parent->left = y;//则将z父节点的左侧指向y
	}else{
		z->parent->right = y;//否则将z父节点的右侧指向y
	}
	y->left = z;//最后将y替换z的位置,将y的左指针指向z
	z->parent = y;//z的父指针指向y
}

进行左旋转时,传入进来的是树的根和要左移动的节点z,所以得根据z来找到z右侧的节点来做左旋转来代替z原来的位置,所以会有 y = z->right 来找到这个节点,然后将找到的右侧节点y的左侧子树变更到z的右侧子树处(因为原来z右侧的值一定是比Z值大的所以肯定是放在Z的右侧的,这个是二叉搜索树的性质,也是红黑树的性质)。变更之后然后再将Y节点的左侧指针指向Z,Y的父指针修改成原来Z的父指针指向的地方,因为Y要替换Z的位置。然后判断一下Z的父节点是否存在,如果不存在则说明Z为根节点,则修改一下树根的指针。如果z原来父节点存在,判断一下原来Z在父节点的左侧还是右侧,将该父节点的左右指针修改指向Y节点,最后将Z放在Y节点的左侧,将z的父指针指向Y节点。


右旋转操作--->代码如下:

void right_rotate(node *tree_root,node *z){
	node *y;
	y= z->parent;//找到z进行右旋转要替换的位置
	y->left = z->right;//将y的左侧子树指向z原来的右子树
	if(z->right!=NULL){
		z->right->parent = y;
	}
	//修改z的父指针,因为z要替换y的位置
	z->parent = y->parent;
	if(y->parent ==NULL){//与左循环一样,判断这个父节点是否为树的根
		tree_root = z;
	}else if(y == y->parent->left){//判读一下z替换y之后再y节点的什么位置
		y->parent->left = z;//左侧的情况
	}else{
		y->parent->right = z;//右侧的情况
	}
	z->right = y;//最后将z的右侧子树指向y
	y->parent = z;//将y的父指针指向z
}


跟左旋转一样,右旋转也要找到其要替换的位置,本右侧旋转要找指定节点的父亲节点位置,所以又 y = z->parent ,找到之后先把z的右侧子树赋值给Y节点的左侧,道理同左旋转(二叉搜索树的性质),然后判断一下z的右侧子树是否为空,为空就不做任何处理,否则修改一下这个右子树的父指针,将其指向Z节点。之后将修改Z的父指针替换Y的父指针。然后判断这个Z是在原Y父节点的左侧还是右侧,最后将z的右指针指向Y,Y的父指针指向Z。


下面Coding红黑树的插入操作:


#define RED 0
#define BLACK 1
typedef struct node{
	int key;
	node *left;
	node *right;
	node *parent;
	int color;
} node;

void RB_insert(node * tree_root,node *z){
	node *y ,*x;
	x= tree_root;
	y = NULL;
	//该while循环是为了找到Z应该插值的地方
	while(x!=NULL){
		y=x;
		if(z->key < y->key){//如果Z的值比Y的值小,则向树的左侧搜索Z的位置
			y = y->left;
		}else{
			y = y->right;//如果Z的值比Y的值大,则向树的右侧搜素Z的位置
		}
	}
	//搜索到了Z的位置之后,将Z的父亲指针指向Y的位置
	z->parent = y;
	//然后随Z是在Y的左侧还是右侧进行判断。
	if(y->parent==NULL){
		tree_root = z;
	}else if(z->key < y->key){
		y->left = z;
	}else{
		y->right = z;
	}
	//最后将Z的左右节点赋值成守卫,并且初始化z的颜色为红色
	z->left = NULL;
	z->right =NULL;
	z->color = RED;
	RB_fixup(tree_root,z);
}
void RB_fixup(node *tree_root,node *z){
	node *y;
	while(z->color ==RED){
		if(z->parent==z->parent->parent->left){
			y = z->parent->parent->right;
			if(y==RED){
				z->parent->color = BLACK;//case1
				y->color = BLACK;		 //case1
				z->parent->parent = RED; //case1
				z = z->parent->parent;	 //case1
			}else if(z==z->parent->right){
				z = z->parent;			 //case2
				left_rotate(tree_root,z);//case2
			}
			z->parent->color =BLACK;	//case3
			z->parent->parent=RED;		//case3
			right_rotate(tree_root,z);	//case3
		}else if(z->parent==z->parent->parent->right){
			y=z->parent->parent->left;
			if(y==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(tree_root,z);
			}
			z->parent->color = BLACK;
			z->parent->parent->color=RED;
			left_rotate(tree_root,z);
		}
	}
	tree_root->color =BLACK;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值