2-3树的插入和删除操作
注意:以下均用2-3树指代2-3查找树
2-3树的定义:
- 2-3树首先是一颗二叉查找树(BST树),也是一颗平衡二叉树(AVL树),所以同时包含两者的性质,
- 2-3树是一颗完美平衡的二叉树,也就是说所有叶子结点到根结点的路径都相同
- 2-3树中包含两种结点:2结点与3结点;如果是2结点,那么一定有一个值和两个孩子,如果是3结点,一定有两个值和3个孩子
- 它是一颗最简单的B树
2-3树结点定义:
template<class T> class tree_23_node //2-3树的结点 {public:tree_23_node();public:int m_type; //用于记录结点的类型,如果是2结点,那么m_type=2,如果是3结点,m_type=3,否则m_type=0;T* m_small_data;T* m_large_data;class tree_23_node<T>*m_parent; //父结点class tree_23_node<T>*m_l_child; //左孩子class tree_23_node<T>*m_m_child; //中孩子class tree_23_node<T>*m_r_child; //右孩子 }template<class T> class tree_23 //2-3树 {public:tree_23();public:class tree_23_node<T>*m_root; }
上图是一颗简单的2-3树,2-3树中序遍历的顺序为:左孩子->当前结点小值->(中结点->当前结点大值)->右孩子,
其中序遍历结果是:8 10 12 14 16 20 24 26 28 32 34 38
查找:
2-3树的查找操作和二叉树的查找操作是一样的,
- 检查当前结点的值,如果当前结点命中,返回true,退出递归;否则向左子树递归查找
- 如果左子树命中,返回true,退出递归;(如果中子树存在)否则向中子树递归查找
- 如果中子树命中,返回true,退出递归;否则向右子树递归查找
- 如果右子树命中,返回true,退出递归;否则当前结点、左子树、(如果存在)中子树、右子树都没有命中,返回false
插入:
注意:2-3树的长高发生在根结点,而不是叶子结点
普通二叉树的插入操作:假设插入的值为data,
- 先找到要插入的叶子结点位置,此叶子结点设为leaf,值为leaf-value
- 新建结点son ,son-value=data,son-l-child=son-r-child=NULL(son的左右孩子都是NULL)
- 再判断leaf-value和data的大小,如果data>leaf-value,则son到leaf的右子树中,否则son到leaf的左子树中
- 注意在上一步时树的高度变化了(树高+1),也就是说树的高度变化发生在叶子结点leaf
2-3树的插入分析:假设插入的值为data,
- 先找到要插入的叶子结点位置,此叶子结点设置为leaf,
- 如果此时新建结点son,son-value=data,插入到leaf的一颗子树中,2-3树的性质(所有叶子结点到根结点的路径都相同)不会满足
- 所以不能新建结点,而是要把data插入到叶子结点leaf中,这样(所有叶子结点到根结点的路径都相同)这条性质可能不会满足
- 如果leaf是2结点,新值data直接插入到leaf,如果leaf是3结点,不能插入新值data,那么将leaf分裂并向上(leaf的父结点)递归处理
- 如果递归到根结点,而根结点也是3结点,那么分裂根结点后,树的高度+1,也就是说2-3树的长高发生在根结点,而不是叶子结点
2-3树的插入操作:假设插入的值为data,
- 如果根结点是NULL,直接将data插入根结点
- 否则先找到data需要插入的叶子结点leaf
- 如果如果插入结点leaf是2结点,直接插入data,leaf变为3结点
- 如果插入结点leaf是3结点,向上(parent)递归寻求解(假设leaf的父结点为parent)
- 如果parent是2结点,这是情况2,直接插入parent并return
- 如果parent是3结点,这是情况3,继续向向上(parent->parnet)递归求解
- 如果parent是结点,单独处理
- 插入操作----情况1:根结点root==NULL,直接将data插入到根结点,根结点变为2结点
- 插入操作----情况2:根结点root!=NULL,首先找到插入的叶子结点leaf,
情况2.1:leaf是2结点,直接向leaf插入data
情况2.2:leaf是3结点,但是leaf的parent是2结点,(注意这里的leaf的孩子是NULL空指针,没有画出来)
情况2.2分析:
由于leaf是3结点,如果直接将9插入到leaf中,那么leaf会变成4结点(leaf会有3个值,4个孩子),不符合2-3树的性质;
解决办法:
- 将leaf中的两个值(small和large两个值)和data比较大小
- 最小的值作为leaf->m_small_data,并且leaf变为2结点,leaf->m_large_data=NULL
- 中间值作为新的data,最大值新建一个结点new_node
- 将data和new_node作为形参往parent递归下去(对parent递归)
- 如果parent是2结点(包含一个键值和两个孩子),将data(键值)和new_node(孩子)与parent的一个键值和两个孩子组合为一个3结点(2个键值和3个孩子)
- 如果parent是3结点,就是下面的情况2.3
如下面的3张图,在创建 新的键值data和新的孩子new_node 时,要考虑数值之间的大小关系,详情见下面的图,并且data和new_node在和parent组成3结点时也要考虑清楚各种情况,总之很繁琐
情况2.3:leaf是3结点,但是leaf的parent也是3结点,(注意这里的leaf的孩子是NULL空指针,没有画出来)
情况2.4:leaf是3结点,但是leaf的parent也是3结点,并且parent是根结点
2-3树中插入的注意事项
1、当前结点分裂形成新的当前结点、新建结点、新值时,一定不能丢失所有的孩子信息,其中当前结点有3个孩子,以及上传的一个孩子(是什么呢?它是前一个新建结点,可以是NULL),共4个孩子,可以形成两个2结点
2、如果是根结点的分裂,要将根结点的m_root的指向及时更新
3、2-3树的长高只能通过根结点的分裂
删除:
注意:2-3树的逆生长(即高度降低)一定使发生在根结点,而不是叶子结点
普通二叉树的删除操作:假设删除的值为data
- 首先是找到待删除结点的位置
- 如果待删除结点是叶子结点,直接删除
- 如果待删除结点是非叶子结点,分情况讨论:
- 待删除结点只有一个孩子,那么直接将父结点和孩子结点建立联系即可
- 待删除结点有两个孩子,找到当前结点的前驱(后继)结点,两结点替换,继续对前驱结点进行结点删除操作
2-3树的删除操作:假设删除的值为data
- 首先找到待删除结点的位置
- 如果待删除结点不是叶子结点,将问题转化为删除叶子结点(通过与前驱或者后继结点替换来转换问题)
- 如果待删除结点是叶子结点,
- 如果删除结点是3结点,直接删除data,删除结点变为2结点,然后return
- 如果删除结点是2结点,首先删除data,删除结点变为0结点
- 如果父兄都是2结点,递归处理
- 如果父兄至少有一个是3结点,从父结点或者兄弟结点借值后组建新的删除结点(变为2结点),然后return
下面我将通过图示来说明:待删除2-3树如下
删除操作----情况1:如果待删除结点不是叶子结点,将问题转化为删除叶子结点
删除操作----情况2:如果待删除结点是叶子结点
情况2.1:删除结点是3结点,直接删除data,删除结点变为2结点,然后return
情况2.2:删除结点是2结点,直接删除data,删除结点变为0结点
情况2.2.1:如果父兄至少有一个3结点,从父结点或者兄弟结点借值后组建新的删除结点(变为2结点),然后return
这种情况是最繁琐的,要分父兄都是2结点、父是2结点兄是3结点、父是3结点兄是2结点这3种情况考虑,还要考虑delete是在父结点的左结点、结点还是右结点,但是具体的操作是一样的,太繁琐了就不具体讨论了,本人共考虑了16小情况,还没有找到简单的解法
情况2.2.2:如果父兄都是2结点,此时待删除结点是0结点,需要递归处理
如果说情况2.2.1是繁琐,那么情况2.2.2就很简洁了,这里我们定义以下0结点,0结点代表结点没有键值,但是不代表没有孩子(注意NULL也视为有一个小孩),什么意思呢?看下面的图示
2-3树中删除的注意事项
1、通过将delete结点从叶子结点向根结点移动,不断地判断delete结点的父兄结点符合哪种状况,如此递归下去,直到找到问题的出口并return,
2、注意当delete的父结点是NULL,那么树逆生长(树的高度-1),这就是2-3树的逆生长(即高度降低)一定使发生在根结点,而不是叶子结点
3、在结点的融合过程中,时刻注意更新每个结点的信息,包括结点类型,结点值,结点的父结点以及子结点
结尾:
作为最简单的B树,2-3树的实现仍然很繁琐,2-3-4树就更加麻烦了,且创建一颗2-3(-4)树的效率可能不尽如人意,而且红黑树作为2-3(-4)树的变种,红黑树的插入和删除更高效快捷,那么理解并且用代码实现2-3树似乎不重要了,但是理解2-3树对理解红黑树是有很大的帮助的,红黑树中的插入情况可以和2-3树中的插入、删除情况有所区别,但区别不大。
本人的2-3树代码太冗长了,就不发出来了。
2-3树的插入和删除操作相关推荐
- 快速了解B+树的插入、删除操作
B+树非常的复杂,这里不进行详细的讲解,只对基本的插入删除操作进行说明. 在B+树中,所有记录节点都是按键值的大小顺序存放在同一层的叶节点中,各叶节点用指针连接.因此在进行插入删除操作时,要进行调整, ...
- AVL树的插入_删除操作实现~
AVL的插入操作:找到所插位置之后,往上寻找可能发生不平衡之处x,若找到x则调整平衡.顶多调整平衡1次. AVL的删除操作:找到删除结点x,类似于二叉查找树一样找到其后继或前驱y,若为x->ri ...
- B树的插入、删除操作
一.简介 B树是什么? 1970年,R.Bayer和E.mccreight提出了一种适用于外查找的树,它是一种平衡的多叉树,称为B树(或B-树.B_树). 一棵m阶B树(balanced tree o ...
- 目录树 删除 数据结构_数据结构:B树和B+树的插入、删除图文详解
B树 1.1B树的定义 B树也称B-树,它是一颗多路平衡查找树.我们描述一颗B树时需要指定它的阶数,阶数表示了一个结点最多有多少个孩子结点,一般用字母m表示阶数.当m取2时,就是我们常见的二叉搜索树. ...
- 数据结构:B树和B+树的插入、删除图文详解
目录 B树 1.1B树的定义 1.2B树的插入操作 1.3B树的删除操作 B+树 2.1 B+树的定义 2.2 B+树的插入操作 2.3 B+树的删除操作 B树 1.1B树的定义 B树也称B-树,它是 ...
- 彻底理解面试难点之rb-tree(红黑树)续--对红黑树的插入和删除操作的一些理解!!!
这里主要讲一下对红黑树的插入和删除操作的一些理解 对于红黑树的一些相关性质的介绍,上篇已经讲了,这里不再介绍,有需要了解的,可以翻前面的博客看看. 1.红黑树的插入操作 对于红黑树的元素插入,我们首先 ...
- 红黑树及其插入、删除操作
在二叉搜索树中,基本操作如结点的插入.删除.查找的性能上界都得不到保证,原因在于二叉搜索树的构造依赖于其结点值的插入顺序,最坏情况下二叉搜索树会退化为单链表(如下图所示).因此我们需要对二叉搜索树做出 ...
- 二叉平衡树的插入和删除操作
[转载]二叉平衡树的插入和删除操作 1. 二叉平衡树 二叉排序树查找.插入和删除操作的时间复杂度和树的深度n有关.构建树时,当先后插入的结点按关键字有序时,二叉排序树退化为单枝树,平均查找长 ...
- c语言二叉排序树的创建与查找,C语言实现二叉查找树的插入和删除操作问题求教...
使用C语言实现二叉查找树的插入和删除操作,但在 return searchBST( T->rchild, val, f, p);出错.这里应该使用了双指针,求教应该怎么改才正确. /* +--- ...
最新文章
- wukong引擎源码分析之索引——part 1 倒排列表本质是有序数组存储
- python写的游戏怎么给别人玩-一步步教你怎么用python写贪吃蛇游戏
- 使用Javaslang进行Java 8中的函数式编程
- 杜克大学计算机硕士要几年,2017杜克大学春季不招计算机专业的硕士?
- java想要生成 字符串,如何在Java中“优雅地”生成String?
- CentOS 6.4 命令行 安装 VMware Tools
- 优秀的电商平台Jshop栗子
- 【ACL2020-CMU-Google】MobileBERT:用于资源受限设备的任务无关“瘦版”BERT
- LEACH路由协议MATLAB仿真代码
- 临床大数据分析与挖掘
- 2021宇哥八套卷总结—第三套试卷分析
- Python办公自动化之文件读写操作与Excel,csv,PDF文件
- esxi 虚拟机的控制台上键盘无法输入
- u3d:200个插件免费分享
- java8:lambda级联表达式(Cascading)或柯里化(Currying)原理简化详解
- .net之实现文件上传与下载
- C# MVC 微信支付教程系列之公众号支付
- iOS关闭键盘的两种简单方法
- Android拉取微信公众号列表,Xposed实时获取微信公众号推送
- Android自定义的下拉列表框控件