连看带写花了三天,中途被指针引用搞得晕晕乎乎的。 插入和删除的调整过程没有看原理,只看了方法,直接照着写的。

看了两份资料,一份是算法导论第12-13章, 另一份是网上的资料http://blog.csdn.net/v_JULY_v/article/details/6105630

下面C代码是我根据 算法导论的伪码写的。

#include <stdio.h>
#include <stdlib.h>
#include <string.h> typedef int DataType; typedef struct RBNode
{
RBNode *parent, *left, *right; //指向结点的父结点、左右孩子结点
DataType key; //结点数据
int color; //颜色 红(r) 或 黑(b)
}RBNode; //定义红黑树结点 RBNode Nil;
RBNode * nil = &Nil; void left_rotate( RBNode * &T, RBNode * x) //左旋 x一定不能有引用 因为如果引用后 x与y->parent就是等价的了, y->parent改变 x就会改变
{
RBNode * y;
y = x->right;
/************第一部分 y的左孩子 与 x间关联*************/
x->right = y->left; //x认右孩子
if(y->left != nil)
{
y->left->parent = x; //孩子认parent
}
/************第一部分 y的左孩子 与 x间关联 end*************/ /************第二部分 y 与 x的parent 关联*************/
y->parent = x->parent; //y认 x的parent为自己的parent //y的parent与x的地址是一样的 int isroot = ;
if(x->parent == nil) //x的parent根据自己的情况 认y为左或右孩子
{
isroot = ;
}
else if(x == x->parent->left)
{
x->parent->left = y;
}
else
{
x->parent->right = y;
}
/************第二部分 y 与 x的parent 关联 end*************/ /************第部分 x 与 y的关联 *************/
y->left = x; //y认x为孩子
x->parent = y; //x认y为parent
/************第部分 x 与 y的关联 end*************/
if(isroot == )
{
T = y;
}
} void right_rotate(RBNode * &T, RBNode * x) //右旋
{
RBNode * y;
y = x->left; x->left = y->right; if(y->right != nil)
{
y->right->parent = x;
} y->parent = x->parent;
int isroot = ;
if(x->parent == nil)
{
isroot = ;
}
else if(x == x->parent->right)
{
x->parent->right = y;
}
else
{
x->parent->left = y;
} y->right = x;
x->parent = y; if(isroot == )
{
T = y;
}
} void rb_insert_fixup(RBNode * &T, RBNode * z) //红黑树插入后的调整 注意z不能要引用 因为调整的过程中z的值作为位置标记会改变 但我们不希望树的结构因为z而变化
{ RBNode * y;
while(z->parent->color == 'r')
{
if(z->parent == z->parent->parent->left) //z的parent是左子的情况
{
//copy(z->parent->parent->right, y);
y = z->parent->parent->right;
if(y->color == 'r') //情况1 z的parent和uncle都是红色 把这两个红色染成黑色 把grandparent染成红色 令z = grandparent 再次循环
{
y->color = 'b';
z->parent->color = 'b';
z->parent->parent->color = 'r';
z = z->parent->parent;
}
else if(z == z->parent->right) //当前节点的父节点是红色,叔叔节点是黑色,当前节点是其父节点的右子 对策:当前节点的父节点做为新的当前节点,以新当前节点为支点左旋。
{
z = z->parent;
left_rotate(T, z);
}
else //当前节点的父节点是红色,叔叔节点是黑色,当前节点是其父节点的左子 解法:父节点变为黑色,祖父节点变为红色,在祖父节点为支点右旋
{
z->parent->color = 'b';
z->parent->parent->color = 'r';
right_rotate(T, z->parent->parent);
}
}
else //z的parent是右子的情况
{
y = z->parent->parent->left;
if(y->color == 'r')
{
z->parent->color = 'b';
y->color = 'b';
z->parent->parent->color = 'r';
z = z->parent->parent;
}
else if(z == z->parent->left)
{
z = z->parent;
right_rotate(T, z);
}
else
{
z->parent->color = 'b';
z->parent->parent->color = 'r';
left_rotate(T, z->parent->parent);
}
}
} if(z->parent == nil)
{
z->color = 'b';
return;
}
else
{
return;
}
} void rb_insert(RBNode * &T, RBNode * z) //红黑树 插入工作 注意 z不要有引用
{
RBNode * y = nil;
RBNode * x = T;
while(x != nil) //找到z适当的插入位置
{
y = x;
if(z->key < x->key)
x = x->left;
else
x = x->right;
} z->parent = y;
if(y == nil) //parent 认孩子总是麻烦一些的 毕竟要区分是左是右 是否为根
{
T = z;
}
else if(z->key < y->key)
{
y->left = z;
}
else
{
y->right = z;
} //对新插入的点处理, 染成红色
z->left = nil;
z->right = nil;
z->color = 'r'; //调整红黑树
rb_insert_fixup(T, z); } RBNode * rb_findmax(RBNode * z) //找到以z为树根的树的最大结点
{
while(z->right != nil)
{
z = z->right;
}
return z;
} RBNode * rb_findmin(RBNode * z) //找到以z为树根的树的最小结点
{
while(z->left != nil)
{
z = z->left;
}
return z;
} RBNode * rb_successor(RBNode * z) //找z的后继
{
if(z->right != nil)
{
return rb_findmin(z->right); //如果z的right不为空 后继就是z的右子树中最小的点
}
else
{
RBNode * y = z->parent;
while(y != nil && z == y->right)
{
z = y;
y = y->parent;
}
return y;
}
} void rb_delete_fixup(RBNode * &T, RBNode * x)
{
RBNode* w;
while(x != T && x->color == 'b')
{
if(x == x->parent->left)
{
w = x->parent->right;
if(w->color == 'r')
{
w->color = 'b';
x->parent->color = 'r';
left_rotate(T, x->parent); w = x->parent->right;
}
if(w->left->color == 'b' && w->right->color == 'b')
{
w->color = 'r';
x = x->parent;
}
else
{
if(w->right->color == 'b')
{
w->left->color = 'b';
w->color = 'r';
right_rotate(T, w);
w = x->parent->right;
} w->color = x->parent->color;
x->parent->color = 'b';
w->right->color = 'b';
left_rotate(T, x->parent);
x = T;
}
}
else
{
w = x->parent->left;
if(w->color == 'r')
{
w->color = 'b';
x->parent->color = 'r';
right_rotate(T, x->parent); w = x->parent->left;
}
if(w->left->color == 'b' && w->right->color == 'b')
{
w->color = 'r';
x = x->parent;
}
else if(w->left->color == 'b')
{
if(w->left->color == 'b')
{
w->right->color = 'b';
w->color = 'r';
left_rotate(T, w);
w = x->parent->left;
} w->color = x->parent->color;
x->parent->color = 'b';
w->left->color = 'b';
right_rotate(T, x->parent);
x = T;
}
}
}
x->color = 'b';
} RBNode * rb_delete(RBNode * &T, RBNode * z) //红黑树 删除节点
{
//y 确定删除的结点是z还是z的后继
RBNode * y;
y = (z->left == nil || z->right == nil) ? z : rb_successor(z); //x 是y的非nil子女 或是 nil
RBNode * x;
x = (y->left != nil) ? y->left : y->right; //无条件令x的parent = y的parent
x->parent = y->parent; //删除y 建立x与y的parent之间的联系
if(y->parent == nil)
{
T = x;
}
else if(y == y->parent->left)
{
y->parent->left = x;
}
else
{
y->parent->right = x;
} //如果y!=z 将y的数据拷贝到z
if(y != z)
{
//z的颜色不变
z->parent = y->parent;
z->left = y->left;
z->right = y->right;
z->key = y->key;
} if(y->color == 'b')
{
rb_delete_fixup(T, x);
}
return y;
}
int main()
{
nil->color = 'b'; //叶子结点都是黑的
nil->left = nil;
nil->right = nil;
nil->parent = nil;
RBNode *T;
T = nil;
RBNode data[];
for(int i = ; i < ; i++)
{
data[i].key = i + ;
RBNode * z = &data[i];
rb_insert(T, z);
} RBNode * x = T->left->left;
rb_delete(T, x); return ;
}

【数据结构】红黑树 C语言代码的更多相关文章

  1. 高级数据结构---红黑树及其插入左旋右旋代码java实现

    前面我们说到的二叉查找树,可以看到根结点是初始化之后就是固定了的,后续插入的数如果都比它大,或者都比它小,那么这个时候它就退化成了链表了,查询的时间复杂度就变成了O(n),而不是理想中O(logn), ...

  2. java数据结构——红黑树(R-B Tree)

    红黑树相比平衡二叉树(AVL)是一种弱平衡树,且具有以下特性: 1.每个节点非红即黑; 2.根节点是黑的; 3.每个叶节点(叶节点即树尾端NULL指针或NULL节点)都是黑的; 4.如图所示,如果一个 ...

  3. 第三十三篇 玩转数据结构——红黑树(Read Black Tree)

    1.. 图解2-3树维持绝对平衡的原理: 2.. 红黑树与2-3树是等价的 3.. 红黑树的特点 简要概括如下: 所有节点非黑即红:根节点为黑:NULL节点为黑:红节点孩子为黑:黑平衡 4.. 实现红 ...

  4. Java数据结构——红黑树

    红黑树介绍红黑树(Red-Black Tree),它一种特殊的二叉查找树.执行查找.插入.删除等操作的时间复杂度为O(logn). 红黑树是特殊的二叉查找树,意味着它满足二叉查找树的特征:任意一个节点 ...

  5. 数据结构和算法(Golang实现)(29)查找算法-2-3树和左倾红黑树

    某些教程不区分普通红黑树和左倾红黑树的区别,直接将左倾红黑树拿来教学,并且称其为红黑树,因为左倾红黑树与普通的红黑树相比,实现起来较为简单,容易教学.在这里,我们区分开左倾红黑树和普通红黑树. 红黑树 ...

  6. 算法设计和数据结构学习_5(BST&AVL&红黑树简单介绍)

    前言: 节主要是给出BST,AVL和红黑树的C++代码,方便自己以后的查阅,其代码依旧是data structures and algorithm analysis in c++ (second ed ...

  7. JAVA中的数据结构 - 真正的去理解红黑树

    一, 红黑树所处数据结构的位置: 在JDK源码中, 有treeMap和JDK8的HashMap都用到了红黑树去存储 红黑树可以看成B树的一种: 从二叉树看,红黑树是一颗相对平衡的二叉树 二叉树--&g ...

  8. Java数据结构和算法(八)--红黑树与2-3树

    红黑树规则: 1.每个节点要么是红色,要么是黑色 2.根节点都是黑色节点 3.每个叶节点是黑色节点 3.每个红色节点的两个子节点都是黑色节点,反之,不做要求,换句话说就是不能有连续两个红色节点 4.从 ...

  9. JAVA中的数据结构 - 1,红黑树

    背景: 在JDK源码中, 有treeMap和JDK8的HashMap都用到了红黑树去存储 红黑树可以看成B树的一种: 二叉树-->搜索二叉树-->平衡搜索二叉树-->B树--> ...

随机推荐

  1. [译]git revert

    git revert git revert用来撤销一个已经提交了的快照. 但不是从项目历史中移除这个commit, 而是生成一个新的commit, 老的commit还是保留在历史项目里面的. 这样做的 ...

  2. 安装SQL Server 2012 『企业中文版』

    安装 SQL Server 前,请详细参阅:计划安装SQL Server2012需求详细http://www.cnblogs.com/chhuang/p/3623198.html 安装 SQL Ser ...

  3. wordpress不用插件实现Pagenavi页面导航功能

    Pagenavi 是一个很好的功能,现在 WordPress 博客一般都是使用 WP-Pagenavi 插件来实现,但是如果插件一多的话整个wordpress效率就降低了,我们力求用尽量少的插件来实现 ...

  4. PHP命名空间入门教程

    PHP5.3当中就引入了“命名空间”的概念,一直都没怎么关注和使用,其实学习它也挺简单的,看官方的教程就行了: 命名空间概述 定义命名空间 定义子命名空间 在同一个文件中定义多个命名空间 使用命名空间 ...

  5. An error in projects

    Error能使系统产生Failure从而导致系统不能达到所需的功能. 曾经,做一个关于酒店管理系统的项目.因为数据库表主外键的连接错误,当对页面的添加桌位功能进行测试时,不能正确的添加. 后通过逐行对 ...

  6. [POJ2586]Y2K Accounting Bug

    [POJ2586]Y2K Accounting Bug 试题描述 Accounting for Computer Machinists (ACM) has sufferred from the Y2K ...

  7. 2016 网易校招内推C/C++第二场8.6

    选择题20个,每个1.5,编程题3个,每个20,简答题1个10分. 解: 第二题,一开始喵了一眼,好开心,这不是水题么,第一反应想到的是递归,然后马上就写了,结果case10%,一脸蒙蔽,数据值很大, ...

  8. 有关lucene的问题

    1.异常:Lock obtain timed out: NativeFSLock 原因:没有及时关闭indexWriter或者indexReader,lucene进行读写的时候会在文件夹里面创建loc ...

  9. 服务器设置SSH 长连接

    1.echo $TMOUT 如果显示空白,表示没有设置, 等于使用默认值0, 一般情况下应该是不超时. 如果大于0, 可以在如/etc/profile之类文件中设置它为0. 2.修改/etc/ssh/ ...

  10. Mysql5.7版本编译安装及配置

    配置yum安装方式 1.配置本地yum源 vim /etc/yum.repos.d/rhel-source.repo [rhel-source] name=Red Hat Enterprise Lin ...