从二叉排序树到平衡二叉树再到红黑树系列3

这篇博客主要讲解B树及其插入删除操作,并给出操作的流程图以达到清晰易懂的目的,尽管标题是从二叉排序树到平衡二叉树再到红黑树系列3,没有B树二字,但他们都是动态查找树,所以我将他们归为一个系列。

B树是为磁盘或其他直接存取的辅助存储设备而设计的一种平衡搜索树。它以一种很自然的方式推广了二叉搜索树,B树与红黑树的不同之处在于B树结点的孩子不限于最多为2,而是可以有数个到数千个不定。因为结点的分支更多,因而相比红黑树,高度更小。

B树的定义有如下两种,但殊途同归。

定义形式一(以度 t 定义):

一棵B树T 具有以下性质:

1.每个结点x有下面属性

a  x.n当前存储在结点x中的关键字个数。

b  x.n个关键字本身,且按非递减顺序排列

c  x.leaf  布尔值 如果x是叶子结点,则为TRUE,否则为FALSE

2.每个内部结点x还包含x.n+1个指向其孩子的指针。(x.n个关键字将一个区间分为x.n+1个子区间,所以有x.n+1个孩子,孩子数=关键字数+1)。叶结点没有孩子,所以它们的没有指向孩子的指针。

3.x.n个关键字对存储在各子树中的关键字范围进行分割。

4 每个叶节点具有相同的深度。即树的高度h

5 每个结点包含的关键字的个数称为度,最小度数t>=2;

a 根结点至少有一个关键字,除了根节点,其他每个结点必须至少(t-1)个关键字

b 每个结点至多包含(2t-1)个关键字,即一个内部结点最多可以有2t个孩子,当一个结点恰好有2t-1个关键字时,称该结点是full的。

struct BNode
{
	int num;//关键字个数
	int key[maximun];//结点中存放的关键字
	struct BNode *parent;//指向双亲结点指针
	struct BNode *ptr[maximum];//关键字的孩子结点指针数组
}

例如 t=2 的B树最简单,每个内部结点可以有2,3,4个孩子,即为一棵2-3-4树。下面给出 t = 2 表示{1,2,3,4,5}的所有合法的B树。

根结点关键字个数最少为1个,最多为3个(显然根有3个关键字,则其要有4个孩子,至少4个关键字,一共7个关键字>5)    其余结点至少1个关键字,至多3个关键字。

一棵包含n个关键字,高度为h 最小度数 t >=2的B数 有如下性质:

<注意:树高h是从1开始算起,即只有根节点的B树高度h=1,与算法导论略有不同>

可以得到:对于一共含有n个关键字 度为 t 的 B树,其高度上限为log(t)((n+1)/2)+1  ,可见 B树是一个非常有效率的数据结构。

下面给出B树定义形式二(按阶定义):

一棵 m 阶的B树满足以下条件:

1 每个结点至多有m棵子树  <==该结点至多m-1个关键字>

2 除根结点,其他分支结点至少有[m/2](取上界)棵子树  
<==至少[m/2]-1个关键字>

3 根结点至少有2棵子树

4 所有叶子结点在同一层,叶子结点不含任何关键字信息

5 有 j 个孩子的非叶子结点恰好有j-1个关键字

事实上,按度定义是从B树结点的关键字个数出发   按阶定义是按B树结点的子树个数出发,都是一样的。

下面主要介绍B树的插入和删除操作:

B树关键字的插入:首先要考虑的是待插入关键字是否存在,若不存在,在查找的过程中就会找到插入结点的位置。插入时主要要考虑的待插入结点是否有足够的空间将关键字插入进去(插入后还要移动元素以保证升序有序)。如果结点空间已满,这时就要分裂结点。并将分裂前结点的中间关键字去除上移给双亲结点。如果双亲结点已满,则需要再度分裂。 最坏的情况是 插入一个关键字,却需要一直分裂到根结点,再新增一个结点,整个B树增加了一层,高度h=h+1;

具体流程图如下:

B树关键字的删除:在删除一个关键字时,首先要找到关键字的位置,并考虑删除后该结点关键字的大小是否满足B树的要求 和 对关键字左右子树的影响。流程图中非删除关键字所在结点是否为叶子结点分类讨论。必要时,要合并子树。最极端的一种情况,因为删除一个关键字,从下往上合并结点,最后导致B树的高度h=h-1.

具体流程图如下:

关于B树插入删除关键字的几点补充说明:

1 关键字的插入 一定是在叶子结点,所以不需要考虑对子树影响,只需要考虑结点可能超过容量,因而要分裂结点。而删除可能发生在非叶子结点,所以要考虑对子树影响,且结点删除一个关键字,可能小于关键字数量下限,因而要合并结点。

2 分裂结点时,父结点的子树多了一个,因而父结点的关键字也要多一个,将待分裂结点中间值上移给父结点,正好划分为两部分且结点容量满足数量要求。

3 删除关键字时,结点关键字个数达到下限,并不急着合并结点,而是先间接向关键字数量较多(较多:借了之后不会导致到达关键字下限)的相邻兄弟结点借关键字(实际过程为向父结点借一个,父结点的缺失由相邻兄弟结点上移一个关键字补充,此为间接之含义)。只有当相邻结点关键值数量都为下限,不能外借时,才会考虑合并。

4 合并结点时,父结点的子树少了一个,因而父结点的关键字也要少一个;因而父节点的一个关键字下移到合并结点中。此时合并结点的关键字数量为(t-1)+1+(t-2)=2t-2

刚好小于每个结点关键字数量上限 (2t-1)。 父节点下移一个关键字后是不是达到下限,如果是,又要重复上述操作(此时,相当于父节点删除了一个元素),回到说明3.

5 插入时达到上限的分裂是必然的,而删除时达到下限的合并不是首先要考虑的,尽量外借关键字以维持B树结构。

B+树

尽管B树的查询效率很高,但是并没有解决元素遍历的效率低下问题,为了解决这个问题,出现了B+树,B+树只需要遍历叶子结点就可以实现整棵树的遍历,特别适合数据库中基于范围的查询。另外对于B+树,所有关键字信息都存储在叶子结点,所以关键字查询的路径长度相同,比较稳定。

B+树是应文件系统所需而出现的一种B树的变形树。一棵m阶的B+树和m阶的B树的区别是:

1   有n棵子树的结点中含有n个关键字

2   所有叶子结点中包含了全部的关键字信息,以及指向这些关键字记录的指针,且叶子结点本身以关键字大小升序排序连接

3   所有非叶子结点可以看为索引部分,结点中仅含有其子树中的最大(或最小)关键字。

参考文献:《算法导论》

http://blog.csdn.net/v_JULY_v/article/details/6530142/

转载请申明:http://blog.csdn.net/u010498696/article/details/46236119

时间: 2024-11-06 03:34:14

从二叉排序树到平衡二叉树再到红黑树系列3的相关文章

从二叉排序树到平衡二叉树再到红黑树系列2

上篇博客主要讲述了二叉排序树的基本概念和插入删除操作,必须再次说明的是:在一棵高度为h的二叉排序树上,实现动态集合操作查询,插入和删除的运行时间均为O(h). 可见二叉树的基本操作效率取决于树的形态,当然树的高度越低越好,显然树分布越均匀,高度越低.那么,问题来了?对于给定的关键字序列,如何构造一棵形态匀称的二叉排序树.这种匀称的二叉排序树就称为平衡二叉树. 平衡二叉树定义:平衡二叉树或为空树,或其上任意一个节点,节点的左右子树高度差不超过1.     通常将二叉树上所有结点的左右子树的高度之差

从二叉排序树到平衡二叉树再到红黑树系列1

最近想写一些关于红黑树的博客,既想写的全面,又直观,但是又不知道从哪里入手.斟酌再三,还是从最简单的二叉排序树开始写. 二叉排序树(Binary Sort Tree)又叫二叉查找树.它是一种特殊结构的二叉树.其或为空树,或具备下列性质: (1)若它的左子树不为空,则左子树上所有结点的值均小于它的根节点的值. (2)若它的右子树不为空,则左子树上所有结点的值均大于它的根节点的值. 显然,它的中序遍历就是一个递增的有序序列. 定理:在一棵高度为h的二叉搜索树上,动态集合上的操作serach,minm

数据结构中常见的树(BST二叉搜索树、AVL平衡二叉树、RBT红黑树、B-树、B+树、B*树)

树 即二叉搜索树: 1.所有非叶子结点至多拥有两个儿子(Left和Right): 2.所有结点存储一个关键字: 非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树: 如: BST树的搜索,从根结点开始,如果查询的关键字与结点的关键字相等,那么就命中: 如果BST树的所有非叶子结点的左右子树的结点数目均保持差不多(平衡),那么B树 的搜索性能逼近二分查找:但它比连续内存空间的二分查找的优点是,改变BST树结构 插入与删除结点)不需要移动大段的内存数据,甚至通常是常数开销: 如:

从二叉树到2-3-4树再到红黑树

直接进入正题: 一.如何从数组生成一个二叉树 假设数组为:{ 30, 13, 7, 43, 23, 12, 9, 33, 42, 21, 18, 6, 3, 50 },我们不对数组排序,直接生成二叉树. 创建流程: 1.将第一数作为根节点: 2.插入13,13小于30,放在30的左边子节点. 3.插入7,7小于30,7小于13,放在13的左边子节点. 4.插入43,43大于30,放在30的右边子节点. 5.放入23,23小于30,23大于13,放入13的右边子节点. 6.放入12,12小于30,

再论红黑树

红黑树: 红黑树(Red Black Tree) 是一种自平衡二叉查找树 : l 每个节点或者是黑色,或者是红色. l 根节点是黑色. l 每个叶子节点是黑色. l 如果一个节点是红色的,则它的子节点必须是黑色的. l 从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点. 红黑树的各种操作的时间复杂度是O(log2N). 红黑树 vs AVL 红黑树的查询性能略微逊色于AVL树,因为他比avl树会稍微不平衡最多一层,也就是说红黑树的查询性能只比相同内容的avl树最多多一次比较,但是,红

为什么要有红黑树?什么是红黑树?画了20张图,看完这篇你就明白了

为什么要有红黑树 想必大家对二叉树搜索树都不陌生,首先看一下二叉搜索树的定义: 二叉搜索树(Binary Search Tree),或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值: 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值: 它的左.右子树也分别为二叉排序树. 从理论上来说,二叉搜索树的查询.插入和删除一个节点的时间复杂度均为O(log(n)),已经完全可以满足我们的要求了,那么为什么还要有红黑树呢? 我们来看一个例

红黑树之添加节点和创建

红黑树之插入节点 红黑树的性质 红黑树是每个节点都带有颜色属性的二叉查找树,颜色或红色或黑色.在二叉查找树强制一般要求以外,对于任何有效的红黑树我们增加了如下的额外要求: 节点是红色或黑色. 根节点是黑色. 每个叶节点(这里的叶节点是指NULL节点,在<算法导论>中这个节点叫哨兵节点,除了颜色属性外,其他属性值都为任意.为了和以前的叶子节点做区分,原来的叶子节点还叫叶子节点,这个节点就叫他NULL节点吧)是黑色的. 每个红色节点的两个子节点都是黑色.(从每个叶子到根的所有路径上不能有两个连续的

为什么红黑树的效率比较高

红黑树属于平衡二叉树.它不严格是因为它不是严格控制左.右子树高度或节点数之差小于等于1,但红黑树高度依然是平均log(n),且最坏情况高度不会超过2log(n). 红黑树(red-black tree) 是一棵满足下述性质的二叉查找树: 1. 每一个结点要么是红色,要么是黑色. 2. 根结点是黑色的. 3. 所有叶子结点都是黑色的(实际上都是Null指针,下图用NIL表示).叶子结点不包含任何关键字信息,所有查询关键字都在非终结点上. 4. 每个红色结点的两个子节点必须是黑色的.换句话说:从每个

数据结构系列(5)之 红黑树

本文将主要讲述平衡二叉树中的红黑树,红黑树是一种我们经常使用的树,相较于 AVL 树他无论是增加还是删除节点,其结构的变化都能控制在常树次:在 JDK 中的 TreeMap 同样也是使用红黑树实现的: 一.结构概述 红黑树是在AVL 树平衡条件的基础上,进一步放宽条件,从而使得红黑树在动态变化的时候,其结构的变化在常数次:其标准大致可以表示为: 任一节点左.右子树的高度,相差不得超过两倍. 同他的名字,红黑树的节点是有颜色的,如图所示: 其性质如下: 树根始终为黑色 外部节点均为黑色(图中的 l