Linux与数据结构 2019-3-24上午

1.红黑树

1.1 红黑树的删除,我们假定Z是被删除节点

  • 1.最简单情况,Z是树的根,且树除了根节点没有其他节点,则直接删除;
  • 2.Z是树的根,且树只有一个红孩子,则将根删除,将孩子节点变黑,成为新的根;
  • 3.Z是红色的叶子节点,则直接删除;
  • 4.Z是黑色的,非根,且只有一个红孩子,则将红孩子与爷爷节点连接,并将孩子变黑;
  • 5.Z是黑色的,非根,且无孩子,则需分类讨论;
    • 5.1 Z的兄弟节点是红色的,父节点和侄子节点都是黑色,需讨论Z是左孩子还是右孩子;
      • 5.1.1 兄弟节点是父节点的右孩子,以父节点为支点进行左旋操作,更新兄弟节点;
      • 5.1.2 兄弟节点是父节点的左孩子,以父节点为支点进行右旋操作,更新兄弟节点;
    • 5.2 Z的兄弟节点是黑色的,分开讨论;
      • 5.2.1 侄子全是黑色的,需要判断父节点是黑还是红;
        • 5.2.1.1 父节点是红色,则将兄弟节点变为红色,将父节点变黑,结束;
        • 5.2.1.2 父节点是黑色,则将兄弟节点变为红色,将父节点当作新Z来重新调整(向上找爷爷节点,向下平衡);
      • 5.2.2 侄子节点左红右黑;
        • 5.2.2.1 兄弟节点是父节点的右孩子,将兄弟节点变红,左侄子节点变黑,以兄弟节点为支点进行右旋操作,更新兄弟节点,进入5.2.3.1;
      • 5.2.3 侄子节点左黑右红;
        • 5.2.3.1 兄弟节点是父节点的右孩子,将右侄子节点变黑,父节点的颜色传给兄弟节点,父节点变黑,以父节点为支点进行左旋,结束;
        • 5.2.3.2 兄弟节点是父节点的左孩子,将兄弟节点变红,右侄子节点变黑,以兄弟节点为支点进行左旋操作,更新兄弟节点,进入5.2.2.2;
        • 5.2.2.2 兄弟节点是父节点的左孩子,将左侄子节点变黑,父节点的颜色传给兄弟节点,父节点变黑,以父节点为支点进行右旋,结束;
// 找到要删除的节点的位置
RBT* Search(RBT* p_tree, int find_num)
{
	while(p_tree)
	{
		if(p_tree->n_value == find_num)
			return p_tree;
		else if(p_tree->n_value < find_num)
			p_tree = p_tree->p_right;
		else
			p_tree = p_tree->p_left;
	}
	return NULL;
}

// 进行删除(红黑树被定义为全局变量p_rbt,因此只需传入一个要删除的值即可)
void DelNode(int del_num)
{
	RBT* p_temp = NULL;					// 要删除的节点的位置
	p_temp = Search(p_rbt, del_num);
	if(p_temp == NULL)return;

	// 记录一下p_temp的孩子节点的情况,要是其有孩子节点,则找其左的最右
	RBT* p_flag = NULL;
	if(p_temp->p_left != NULL && p_temp->p_right != NULL)
	{
		p_flag = p_temp;
		p_temp = p_temp->p_left;
		while(p_temp->p_right)
		{
			p_temp = p_temp->p_right;
		}
	}

	// 1.只有一个黑色的根节点的树
	RBT* p_node = p_temp->p_father;
}

猜你喜欢

转载自blog.csdn.net/weixin_42896619/article/details/88942047
今日推荐