不带父结点的红黑树实现

由于只看到13.3节,所以暂时只实现旋转插入函数。

思考:如果不带父结点,那么在需要访问z的父结点时,我们可以借助查找函数从根结点到待查找结点z的路径上必然能找到z的父结点和祖父结点,所以由此可访问父结点。不过这种方法使得旋转函数时间增加到O(lgn),而插入函数也相应的增加到O(lgnlgn)。节省了空间上的内存,同时增加了运行时间。

具体代码如下:

#include <iostream>
using namespace std;
#define BLACK 0
#define RED 1
#define Nil -1
#define LEN sizeof(struct Tree)
struct Tree
{
   struct Tree*left;
   struct Tree*right;
   int key;
   int color;
};
struct Tree*root=NULL;
struct Tree*nil=NULL;
//非递归版本的二叉查找树查找函数
struct Tree*ITERATIVE_TREE_SEARCH(struct Tree*x,int k,struct Tree*&p1,struct Tree*&p2)
{//
	while (x!=nil&&k!=x->key)
	{
		p1=x;
		if (k<x->key)
		{
			x=x->left;
		}
		else x=x->right;
		if(k!=x->key)//如果没找到了待查找值,那么继续记录其祖父和父结点值。
		{
            p2=p1;
			p1=x;
		}
	}
	return x;
}
void LEFT_ROTATE(struct Tree*T,struct Tree*x)
{//左旋转:分三个步骤①②③来叙述旋转代码的。
	struct Tree*p1=nil,*p2=nil;
	struct Tree*y=x->right;//设置y结点。
	x->right=y->left;//本行代码以及下面的if结构表达的是“y的左孩子成为x的右孩子”。①
	ITERATIVE_TREE_SEARCH(root,x->key,p1,p2);
	if(p1==nil)//本行代码以及下面的if-else结构表达的过程是“y成为该子树新的根”。②
	{
       root=y;
	}
	else if(x==p1->left)
	{
       p1->left=y;
	}
	else p1->right=y;
	y->left=x;//本行代码以及下面一行都表达了“x成为y的左孩子”。③
}
void RIGHT_ROTATE(struct Tree*T,struct Tree*x)
{//右旋转
	struct Tree*p1=nil,*p2=nil;
	struct Tree*y=x->left;
	x->left=y->right;
	ITERATIVE_TREE_SEARCH(root,x->key,p1,p2);
	if(p1==nil)
	{
		root=y;
	}
	else if(x==p1->right)
	{
		p1->right=y;
	}
	else p1->left=y;
	y->right=x;
}
void RB_INSERT_INSERT_FIXUP(struct Tree*T,struct Tree*z)
{
   struct Tree*p1=nil,*p2=nil;
   ITERATIVE_TREE_SEARCH(root,z->key,p1,p2);//p1=z->parent,p2=z->parent->parent
   while (1)
   {
	   ITERATIVE_TREE_SEARCH(root,z->key,p1,p2);//p1是父结点 p2是祖父结点
	   if (p1->color!=RED)
	   {
		   break;
	   }
	   if (p1==p2->left)
	   {
		   struct Tree*y=p2->right;//叔结点
		   if (y->color==RED)//情况一:叔结点为红色
		   {//给p1,y,p2着色以保持性质5。并且解决了z的父结点和z都是红色结点问题
			   p1->color=BLACK;
			   y->color=BLACK;
			   p2->color=RED;
			   z=p2;//把z的祖父结点当成新结点z进入下一次循环
		   }
		   else
		   {
			   if (z==p1->right)//情况二:检查z是否是一个右孩子且叔结点为黑色,前提是p1结点不是叶子结点
			   {//使用一个左旋让情况2转变为情况3
				   z=p1;
				   LEFT_ROTATE(T,z);//由于进入if语句后可知旋转结点不可能是叶子结点,这样就不用判断z是否是叶子结点了。
				   ITERATIVE_TREE_SEARCH(root,z->key,p1,p2);//p1=z->parent,p2=z->parent->parent
			   }
               p1->color=BLACK;//情况三:是z是一个左孩子且叔结点为黑色,改变z的父和祖父结点颜色并做一次右旋,以保持性质5。
			   p2->color=RED;
			   if(p2!=nil) RIGHT_ROTATE(T,p2);//由于p2可能是叶子结点,所以最好还是用一个if判断
		   }
	   }
	   else//下面else分支类似于上面
	   {
		   struct Tree*y=p2->left;
		   if (y->color==RED)
		   {
			   p1->color=BLACK;
			   y->color=BLACK;
			   p2->color=RED;
			   z=p2;
		   }
		   else
		   {
			   if (z==p1->left)
			   {
				   z=p1;
				   RIGHT_ROTATE(T,z);
				   ITERATIVE_TREE_SEARCH(root,z->key,p1,p2);
			   }
               p1->color=BLACK;
			   p2->color=RED;
			   if(p2!=nil) LEFT_ROTATE(T,p2);
		   }
	   }
   }
   root->color=BLACK;//最后给根结点着为黑色。
}
void RB_INSERT(struct Tree*T,struct Tree*z)
{
	struct Tree*y=nil;
	struct Tree*x=root;
	while (x!=nil)
	{
		y=x;
		if (z->key<x->key)
		{
			x=x->left;
		}
		else x=x->right;
	}
	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_INSERT_FIXUP(T,z);
}
//中序遍历
void InOderTraverse(struct Tree *p)
{
    if (p!=nil)
	{
		InOderTraverse(p->left);
		cout<<p->key<<" "<<p->color<<" "<<endl;
		InOderTraverse(p->right);
	}
}
void main()
{
	nil=new struct Tree[LEN];
	nil->key=Nil;nil->color=BLACK;
	root=nil;
	int i=0;
	struct Tree*ROOT=new struct Tree[LEN];
	cin>>ROOT->key;
	RB_INSERT(nil,ROOT);
	root=ROOT;
    while (i!=12)
    {
		struct Tree*z=new struct Tree[LEN];
		cin>>z->key;
		RB_INSERT(root,z);
		i++;
    }
	InOderTraverse(root);
}



不带父结点的红黑树实现

时间: 2024-10-10 09:49:25

不带父结点的红黑树实现的相关文章

算法11---红黑树不带父结点指针的插入实现

算法11---红黑树不带父结点指针的插入实现 1 #include <iostream> 2 using namespace std; 3 #define BLACK 0 4 #define RED 1 5 #define Nil -1 6 #define LEN sizeof(struct Tree) 7 struct Tree 8 { 9 struct Tree*left; 10 struct Tree*right; 11 int key; 12 int color; 13 }; 14 s

Java集合详解6:这次,从头到尾带你解读Java中的红黑树

<Java集合详解系列>是我在完成夯实Java基础篇的系列博客后准备开始写的新系列. 这些文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下Star.fork哈 文章首发于我的个人博客: www.how2playlife.com 什么是红黑树 首先,什么是红黑树呢? 红黑树是一种"平衡的"二叉查找树,它是一种经典高效的算法,能够保证

红黑树的插入与删除

红黑树(Red Black Tree) 是一种自平衡二叉查找树.红黑树和AVL树类似,都是在进行插入和删除操作时通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能.红黑树可以在O(log n)时间内完成查找,插入和删除操作. 二叉搜索树可以看 二叉搜索树 AVL树可以看 AVL树的插入与删除 1. 红黑树的性质 红黑树的自平衡依赖于它的以下性质: 性质1. 结点是红色或黑色. 性质2. 根结点是黑色. 性质3. 每个结点节点(NIL结点,空结点,与其它二叉搜索树不同,红黑树将叶子结点的孩子

深入理解红黑树及C++实现

介绍 红黑树是一种特殊的平衡二叉树(AVL),可以保证在最坏的情况下,基本动态集合操作的时间复杂度为O(logn).因此,被广泛应用于企业级的开发中. 红黑树的性质 在一棵红黑树中,其每个结点上增加了一个存储位(属性color)来表示结点的颜色,且颜色只能是red or black.通过对任何一条从根到叶子的简单路径上各个结点的颜色进行约束,红黑树确保没有一条路径会比其他路径长出2倍,因而是近似于平衡的. 树中每个结点包含5个属性:color.val.lchild.rchild和p(可选).如果

红黑树&mdash;&mdash;算法导论(15)

1. 什么是红黑树 (1) 简介     上一篇我们介绍了基本动态集合操作时间复杂度均为O(h)的二叉搜索树.但遗憾的是,只有当二叉搜索树高度较低时,这些集合操作才会较快:即当树的高度较高(甚至一种极端情况是树变成了1条链)时,这些集合操作并不比在链表上执行的快.     于是我们需要构建出一种"平衡"的二叉搜索树.     红黑树(red-black tree)正是其中的一种.它可以保证在最坏的情况下,基本集合操作的时间复杂度是O(lgn). (2) 性质     与普通二叉搜索树不

算法导论学习---红黑树具体解释之插入(C语言实现)

前面我们学习二叉搜索树的时候发如今一些情况下其高度不是非常均匀,甚至有时候会退化成一条长链,所以我们引用一些"平衡"的二叉搜索树.红黑树就是一种"平衡"的二叉搜索树,它通过在每一个结点附加颜色位和路径上的一些约束条件能够保证在最坏的情况下基本动态集合操作的时间复杂度为O(nlgn).以下会总结红黑树的性质,然后分析红黑树的插入操作,并给出一份完整代码. 先给出红黑树的结点定义: #define RED 1 #define BLACK 0 ///红黑树结点定义,与普通

数据结构:红黑树解析

本文参考:Google.算法导论.STL源码剖析.计算机程序设计艺术. 推荐阅读: Left-Leaning Red-Black Trees, Dagstuhl Workshop on Data Structures, Wadern, Germany, February, 2008,直接下载:http://www.cs.princeton.edu/~rs/talks/LLRB/RedBlack.pdf. 本文的github优化版:https://github.com/julycoding/The

数据结构--树--红黑树

R-B Tree简介 R-B Tree,全称是Red-Black Tree,又称为“红黑树”,它一种特殊的二叉查找树.红黑树的每个节点上都有存储位表示节点的颜色,可以是红(Red)或黑(Black). 红黑树的特性:(1)每个节点或者是黑色,或者是红色.(2)根节点是黑色.(3)每个叶子节点(NIL)是黑色. [注意:这里叶子节点,是指为空(NIL或NULL)的叶子节点!](4)如果一个节点是红色的,则它的子节点必须是黑色的.(5)从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点.

红黑树(Red Black Tree)

介绍另一种平衡二叉树:红黑树(Red Black Tree),红黑树由Rudolf Bayer于1972年发明,当时被称为平衡二叉B树(symmetric binary B-trees),1978年被Leonidas J. Guibas 和 Robert Sedgewick改成一个比较摩登的名字:红黑树. 红黑树和之前所讲的AVL树类似,都是在进行插入和删除操作时通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能.自从红黑树出来后,AVL树就被放到了博物馆里,据说是红黑树有更好的效率,更高