2-3查找树(3阶B-树)

B-树特点:

1.根节点至少有两个子节点

2.每个节点有m-1个key值,升序排列,value也按照键值排列,左边的小于key1,中间的between key1 key2,右边的大于key2

3.其他节点至少有m/2个节点


插入时,可以把节点先插入如2-3树,如果已经有3个节点,可以先假设为4个节点的,然后再提升。


以下转自http://www.cnblogs.com/yangecnu/p/Introduce-2-3-Search-Tree.html

浅谈算法和数据结构: 八 平衡查找树之2-3树


前面介绍了二叉查找树(Binary Search Tree),他对于大多数情况下的查找和插入在效率上来说是没有问题的,但是他在最差的情况下效率比较低。本文及后面文章介绍的平衡查找树的数据结构能够保证在最差的情况下也能达到lgN的效率,要实现这一目标我们需要保证树在插入完成之后始终保持平衡状态,这就是平衡查找树(Balanced Search Tree)。在一棵具有N 个节点的树中,我们希望该树的高度能够维持在lgN左右,这样我们就能保证只需要lgN次比较操作就可以查找到想要的值。不幸的是,每次插入元素之后维持树的平衡状态太昂贵。所以这里会介绍一些新的数据结构来保证在最坏的情况下插入和查找效率都能保证在对数的时间复杂度内完成。本文首先介绍2-3查找树(2-3 Search Tree),后面会在此基础上介绍红黑树和B树。

定义

和二叉树不一样,2-3树运行每个节点保存1个或者两个的值。对于普通的2节点(2-node),他保存1个key和左右两个自己点。对应3节点(3-node),保存两个Key,2-3查找树的定义如下:

1. 要么为空,要么:

2. 对于2节点,该节点保存一个key及对应value,以及两个指向左右节点的节点,左节点也是一个2-3节点,所有的值都比key有效,有节点也是一个2-3节点,所有的值比key要大。

3. 对于3节点,该节点保存两个key及对应value,以及三个指向左中右的节点。左节点也是一个2-3节点,所有的值均比两个key中的最小的key还要小;中间节点也是一个2-3节点,中间节点的key值在两个跟节点key值之间;右节点也是一个2-3节点,节点的所有key值比两个key中的最大的key还要大。

如果中序遍历2-3查找树,就可以得到排好序的序列。在一个完全平衡的2-3查找树中,根节点到每一个为空节点的距离都相同。

Definition of 2-3 tree

查找

在进行2-3树的平衡之前,我们先假设已经处于平衡状态,我们先看基本的查找操作。

2-3树的查找和二叉查找树类似,要确定一个树是否属于2-3树,我们首先和其跟节点进行比较,如果相等,则查找成功;否则根据比较的条件,在其左中右子树中递归查找,如果找到的节点为空,则未找到,否则返回。查找过程如下图:

search in 2-3 tree

插入

往一个2-node节点插入

往2-3树中插入元素和往二叉查找树中插入元素一样,首先要进行查找,然后将节点挂到未找到的节点上。2-3树之所以能够保证在最差的情况下的效率的原因在于其插入之后仍然能够保持平衡状态。如果查找后未找到的节点是一个2-node节点,那么很容易,我们只需要将新的元素放到这个2-node节点里面使其变成一个3-node节点即可。但是如果查找的节点结束于一个3-node节点,那么可能有点麻烦。

insert new node into 2-node

往一个3-node节点插入

往一个3-node节点插入一个新的节点可能会遇到很多种不同的情况,下面首先从一个最简单的只包含一个3-node节点的树开始讨论。

只包含一个3-node节点

Insert into a single 3-node

 

 

如上图,假设2-3树只包含一个3-node节点,这个节点有两个key,没有空间来插入第三个key了,最自然的方式是我们假设这个节点能存放三个元素,暂时使其变成一个4-node节点,同时他包含四个子节点。然后,我们将这个4-node节点的中间元素提升,左边的节点作为其左节点,右边的元素作为其右节点。插入完成,变为平衡2-3查找树,树的高度从0变为1。

节点是3-node,父节点是2-node

和第一种情况一样,我们也可以将新的元素插入到3-node节点中,使其成为一个临时的4-node节点,然后,将该节点中的中间元素提升到父节点即2-node节点中,使其父节点成为一个3-node节点,然后将左右节点分别挂在这个3-node节点的恰当位置。操作如下图:

Insert into a 3-node whose parent is a 2-node

节点是3-node,父节点也是3-node

当我们插入的节点是3-node的时候,我们将该节点拆分,中间元素提升至父节点,但是此时父节点是一个3-node节点,插入之后,父节点变成了4-node节点,然后继续将中间元素提升至其父节点,直至遇到一个父节点是2-node节点,然后将其变为3-node,不需要继续进行拆分。

Insert into a 3-node whose parent is a 3-node

 

 

 

根节点分裂

当根节点到字节点都是3-node节点的时候,这是如果我们要在字节点插入新的元素的时候,会一直查分到跟节点,在最后一步的时候,跟节点变成了一个4-node节点,这个时候,就需要将跟节点查分为两个2-node节点,树的高度加1,这个操作过程如下:

Insert into a 3-node whose parent is a 3-node

本地转换

将一个4-node拆分为2-3node涉及到6种可能的操作。这4-node可能在跟节点,也可能是2-node的左子节点或者右子节点。或者是一个3-node的左,中,右子节点。所有的这些改变都是本地的,不需要检查或者修改其他部分的节点。所以只需要常数次操作即可完成2-3树的平衡。

 

splite a 4-node is a local transformation

性质

这些本地操作保持了2-3树的平衡。对于4-node节点变形为2-3节点,变形前后树的高度没有发生变化。只有当跟节点是4-node节点,变形后树的高度才加一。如下图所示:

global property of 2-3 tree

 

分析

完全平衡的2-3查找树如下图,每个根节点到叶子节点的距离是相同的:

perfect balanced 2-3 tree

2-3树的查找效率与树的高度是息息相关的。

  • 在最坏的情况下,也就是所有的节点都是2-node节点,查找效率为lgN
  • 在最好的情况下,所有的节点都是3-node节点,查找效率为log3N约等于0.631lgN

距离来说,对于1百万个节点的2-3树,树的高度为12-20之间,对于10亿个节点的2-3树,树的高度为18-30之间。

对于插入来说,只需要常数次操作即可完成,因为他只需要修改与该节点关联的节点即可,不需要检查其他节点,所以效率和查找类似。下面是2-3查找树的效率:

analysis of 2-3 tree

实现

直接实现2-3树比较复杂,因为:

  1. 需要处理不同的节点类型,非常繁琐
  2. 需要多次比较操作来将节点下移
  3. 需要上移来拆分4-node节点
  4. 拆分4-node节点的情况有很多种

2-3查找树实现起来比较复杂,在某些情况插入后的平衡操作可能会使得效率降低。在2-3查找树基础上改进的红黑树不仅具有较高的效率,并且实现起来较2-3查找树简单。

但是2-3查找树作为一种比较重要的概念和思路对于后文要讲到的红黑树和B树非常重要。希望本文对您了解2-3查找树有所帮助。

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
用C++语言实现图书管理系统 摘 要 图书管理系统主要是对图书的录入、读者借阅、读者归还等功能进行实现。本课程设计 的系统开发平台为Windows XP,程序设计语言为C++,程序运行平台为Windws98/2000/XP/Seven。在程序设计中采用 了B-方法提高书籍的查找速度。 关键词 程序设计;图书管理系统; C++;数据结构;B- 1 索引 1.1课程设计目的 设计一个小型的图书管理系统,可以实现新增图书,读者借阅,读者归还等功能。 1.2.系统性能要求 能较快的查到所要查找的图书;能准确统计当前每种书的库存,以确定此书是否可以外 借;并且对外借的图书进行管理,记录借出时间、应还时间等。 1.3.功能的实现 1) 新书入库:确定书号后,登记到图书帐目表中,如果表中已有,则只将库存量增加; 2) 借阅:如果一种书的现存量大于0,则借出一本,登记借阅者的书证号和归还期限,改变 现存量; 3)归还:注销对借阅者的登记,改变该书的现存量。 2 系统详细设计及实现 1.所用的知识体系 在整个程序的设计过程当中,用到了C++的一些基础知识,面向对象的思想和结构化 的程序设计思想。数据结构的B-建立索引,用索引提高查找的效率等。 2.系统功能组成框图 3 . 系统功能模块划分 " " 摸块保称 "功能说明 " "1 "系统管理 "显示库存,借阅,归还 " "2 "图书管理 "图书的添加,查询等操作 " "3 "借还书管理 "对每次借书信息的添加,删除等操作 " 4.流程图 4.1录入图书信息 4.2借阅图书 4.3归还图书 5 功能实现 5.1 运行程序的主界面 图5—1 操作界面 5.2 新书入库功能的操作界面 图5-2新书入库 5.3 查询数据的界面 图5-3查询书籍 5.4 查询所有书籍的界面 图 5-4显示库存 5.5 图书借阅的界面 图5-5借阅书籍 5.6 还书的界面 图5-6还书 3 参考文献 [1] 谭浩强 C语言设计(第三版)清华大学出版社 [2] 严蔚敏 吴伟民 数据结构(C语言版) 清华大学出版社 [3] 谭浩强 C++ 程序设计清华大学出版社 [4]参考网址http://www.php.net/manual/zh/function.fopen.php [5]参考网址http://hi.baidu.com/%B3%D5%B3%D5%B5%C4145/blog/item/48f2b1ed1d99d 1d2b21cb15c.html 附录 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<conio.h> #include<time.h> //定义局变量 #define N 10000 //表示状态的字段 #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #define OVERFLOW -2 typedef int Status; typedef char *string ; #define m 3 //B-,设为 // 借阅者的结构体 typedef struct User{ unsigned int number; //借书证号码 int year; int month; int day; //借书时间 int dyear; //截至日期的年 int dmonth; //截至日期的月 int dday; //截至日期的日 struct User *next; //下一个借阅者 }User; //定义用户的的信息 //书的结构体 struct Book{ unsigned int key; //图书的书号 char bname[20]; // 书名 char writter[20]; // 著者 unsigned int left; // 现存量 unsigned int total; // 总存量 User *user; //借阅该书的人 }b[N]; //定义书的信息 //B- 的存储结构 typedef Book KeyType; typedef struct BTNode{ int keynum; //结点中关键字个数,即结点的大小 struct BTNode *parent; //指向双亲结点 KeyType key[m + 1]; //关键字向量,号单元未用 struct BTNode *ptr[m + 1]; //子指针向量 }BTNode,*BTree; //查找结果的存储结构体 typedef struct{ BTNode *pt; //指向找到的结点 int i; //1……m,在结
西南交大;西南交通大学;数据结构;赵宏宇;一、查找 1. 算法设计题 :已知n元顺序表a0, a1, … , an-1按关键字递增有序存储。给定关键字值key,编写算法用对分查找求下标i,满足ai-1<key且aikey。 2. 编程题:输入n个两两互不相等的整数,以这些整数为关键字建立平衡的二叉排序。判断该二叉是否为平衡的,输出判断结果;输出该二叉的中序遍历关键字访问次序。 3. 从空起连续插入以下20个关键字构建m=4的B-。 50, 15, 09, 18, 03, 85, 33, 72, 48, 22, 91, 88, 11, 99, 06, 56, 68, 77, 43, 36。 4. 16个关键字组成的5B-如下图所示,请按关键 字递减的次序删除所有结点至空,画出每删除1个关键字后得到B-,直至空。 5. 12个关键字如本电子教案例1所示,设H(K)=K mod 13,地址空间范围0~15,用二次探测再散列解决冲突。画出哈希表;若各元素等概率查找,求成功查找时的平均查找长度。 二、 内部排序 1. 算法设计与分析题:将直接插入排序的内循环改造为使用对分查找实现元素插入,请写出基于对分查找的插入排序算法并给出其时间复杂度分析。 2. 算法设计:将教案给出的非递归直接插入排序和冒泡排序算法用递归算法实现。 3. 算法设计:带附加头结点单链表将各数据结点按关键字升序连接。 4. 编程题:键盘输入n个无符号整数,用链式基数排序实现由小到大排序,输出排序结果。 提示:对于C语言32bit宽的unsigned类型,可以采用16进制形式来实现基数排序,即32bit共有8个16进制位,每个16进制位进行一趟分配和收集,共8趟

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值