以前看过几次红黑树的介绍,但是一直感觉云里雾里的,不是很明白,什么LL旋转、RR旋转之类的,分类讨论也不是很清晰,前几天偶然网上碰到一本电子书:[麻省理工学院-算法导论].Introduction.to.Algorithms,看过后感觉豁然开朗,书中描述的比较清楚,看过后代码的实现很简单。
关于红黑树的介绍,cnblog的abatei老兄的文章写得比较详细,详情请点击这里
关于红黑树的查找就不用说了(就是二叉树的查找),这里主要说一下插入和删除。
红黑树其实就是特殊的二叉树,要满足一下五个条件:
1、 每个结点的颜色只能是红色或黑色。
2、 根结点是黑色的。
3、 每个叶子结点都带有两个空的黑色结点(被称为黑哨兵)
4、 如果一个结点是红的,则它的两个儿子都是黑的。也就是说在一条路径上不能出现相邻的两个红色结点。
5、 对于每个结点来说,从该结点到其子孙叶结点的所有路径上包含相同数目的黑结点。
插入:插入主要分为两个步骤,首先就是简单的二叉树的插入,然后就是红黑树的调整。
每次经过第一步骤插入新元素后,首先将此节点的颜色置为红色,然后调整红黑树,大体分为两种:当前插入的节点的父节点是其祖父节点的左节点或者右节点(其实说白了就是一种,因为左、右是对称的);而每种又有三种情形,下面只讨论当前插入的节点色父节点是左子节点的情况,因为右是对称的:
1. 当前节点的父节点的兄弟节点的颜色为红色:将当前节点的父节点和父节点的兄弟节点都置为黑色,并将祖父节点置为红色,然后将当前节点指向祖父节点,继续
2. 当前节点为其父节点的右子节点:当前节点指向其父节点,然后以当前节点为顶点进行左旋转
3. 当前节点为其父节点的左子节点:当前节点的父节点置为黑色,祖父节点置为红色,然后以祖父节点为顶点进行右旋转
每种情况的解决都要确保不影响当前节点的子树满足红黑树的5个性质。
删除:删除也是两个步骤,简单的二叉树的删除以及红黑树的调整,但是比插入复杂多了
只有在删除黑色节点的情况下才需要调整红黑树,而删除红色节点并不会破坏红黑树的结构
由于左右的对称性,这里只讨论左边的情况:
1. 当前节点的兄弟节点为红色节点
2. 当前节点的兄弟节点的子节点都为黑色
3. 当前节点的兄弟节点的右子节点为黑色
4. 当前节点的兄弟节点的左子节点为黑色
具体实现请参照下面的代码,我就不再赘述了^_^
具体代码如下:
rbtree.h
rbtree.c