编程内功修炼之数据结构—BTree(三)总结
BTree必须通过各种编程约束,使得不脱离BTree的本身特性;
1)BTree关键字插入操作;插入过程中,如果节点关键字达到上限,添加分裂约束,从而控制每个节点的关键字数维持在 t-1~2*t-1内;
2)BTree节点中的关键字查询;因为关键字按非降序进行排列,所以可以采用二分查找方法进行查询,以提高算法性能;
3)BTree关键字删除操作;
删除操作必须保证节点关键字数n[x]>=t,这样删除一个关键字才不会违反BTree规则。
当前节点是叶节点,可以直接删除;
当前节点是内节点,可以寻找左右子女节点进行关键字替代;
当前节点不足t方案:
(a)如果当前节点关键字不足t,可以向兄弟节点进行借取;
(b)如果左右相近兄弟节点都不满足>=t要求,那么可以采用合并方式;
Delete实现方法如下:
public void delete(BTreeNode node, Integer key){
//删除关键字时,必须保证关键字大于等于t
assert node.size() >=t || node == root;
//对当前节点进行二分查找
ResultSearch resultSearch = divideSearch(node.getKeys(), key);
//成功
if(resultSearch.result){
//如果当前节点属于叶子节点,可以直接进行删除
if(node.isLeaf()){
node.getKeys().remove(resultSearch.index.intValue());
}else{
//如果不是叶子节点 ,判断前于key子节点状态
BTreeNode leftChildNode = node.childAt(resultSearch.index);
if(leftChildNode.size() >= t){
//从leftChildNode进行借值 代替当前需要删除的关键字
//删除当前节点关键字
node.getKeys().remove(resultSearch.index.intValue());
node.insertKey(leftChildNode.keyAt(leftChildNode.size()-1), resultSearch.index);
delete(leftChildNode, leftChildNode.keyAt(leftChildNode.size()-1));
}else{
BTreeNode rightChildNode = node.childAt(resultSearch.index + 1);
if(rightChildNode.size() >= t){
//从rightChildNode进行借值 代替当前需要删除的关键字
node.getKeys().remove(resultSearch.index.intValue());
node.insertKey(rightChildNode.keyAt(0), resultSearch.index);
delete(rightChildNode, rightChildNode.keyAt(0));
}else{
//对于索引的左右子节点的数量都等于t-1
//合适进行合并
//1.将父节点删除 将节点右子节点删除
node.getKeys().remove(resultSearch.index.intValue());
node.getChildrens().remove(resultSearch.index.intValue() + 1);
//2.将父节点添加到左子节点上
leftChildNode.getKeys().add(key);
//3.将删除的右子节点添加到左子节点上
for(int i=0 ; i<rightChildNode.size() ; i++){
leftChildNode.getKeys().add(rightChildNode.getKeys().get(i));
}
//如果右子节点非叶子节点,需要将其子女继承到左节点之下
if(!rightChildNode.isLeaf()){
for(int k=0 ; k<=rightChildNode.size() ; k++){
leftChildNode.getChildrens().add(rightChildNode.childAt(k));
}
}
//递归删除
delete(leftChildNode, key);
}
}
}
}else{ //失败
if(node.isLeaf()){
//不存在删除的对象
System.out.println("不存在删除的对象");
return ;
}
//获取子节点
BTreeNode childNode = node.childAt(resultSearch.index);
if(root == node && node.size()==0){
root = childNode;
}
if(childNode.size() >= t){ //如果满足递归条件
delete(childNode, key);
}else{
//不满足size == t
//采取借关键字手段
BTreeNode subNode = null;
int subIndex = 0;
//先检测右兄弟节点
if(resultSearch.index < node.size()){
if(node.childAt(resultSearch.index+1).size() >=t){
subNode = node.childAt(resultSearch.index+1);
subIndex = resultSearch.index + 1;
}
}
//测试左兄弟节点
if(subNode == null){
if(resultSearch.index > 0){
if(node.childAt(resultSearch.index-1).size() >= t){
subNode = node.childAt(resultSearch.index-1);
subIndex = resultSearch.index - 1;
}
}
}
//测试完成后
if(subNode != null){ //存在兄弟节点大于等于t情况
//判断节点
if(subIndex > resultSearch.index){ //右兄弟
//将右关键字插入自身
childNode.insertKey(node.keyAt(subIndex - 1), childNode.size());
node.getKeys().remove(subIndex - 1);
node.insertKey(subNode.keyAt(0), subIndex - 1);
subNode.getKeys().remove(0);
//右兄弟非子叶节点,则带有孩子节点
if(!subNode.isLeaf()){
childNode.getChildrens().add(subNode.getChildrens().get(0));
subNode.getChildrens().remove(0);
}
}else{ //左兄弟
//将左关键字插入自身最前位置
childNode.insertKey(node.keyAt(subIndex), 0);
node.getKeys().remove(subIndex);
node.insertKey(subNode.keyAt(subNode.size()-1), subIndex);
subNode.getKeys().remove(subNode.size()-1);
//如果左兄弟非子叶节点
if(!subNode.isLeaf()){
childNode.insertChild(subNode.childAt(subNode.size()), 0);
subNode.getChildrens().remove(subNode.size()-1);
}
}
delete(childNode, key);
}else{
//该节点的左右兄弟节点关键字都为t-1
//选择合并方案
if(resultSearch.index < node.size()){ //右兄弟存在
subNode = node.childAt(resultSearch.index + 1);
//childNode.getKeys().add(node.keyAt(resultSearch.index + 1));
childNode.getKeys().add(node.keyAt(resultSearch.index));
node.getKeys().remove(resultSearch.index.intValue());
node.getChildrens().remove(resultSearch.index.intValue());
for(int i=0 ; i<subNode.size() ; i++){
childNode.getKeys().add(subNode.keyAt(i));
}
if(!subNode.isLeaf()){
for(int k=0 ; k<=subNode.size(); k++){
childNode.getChildrens().add(subNode.childAt(k));
}
}
}else{ //左兄弟存在
subNode = node.childAt(resultSearch.index - 1);
childNode.insertKey(node.keyAt(resultSearch.index-1), 0);
node.getKeys().remove(resultSearch.index - 1);
node.getChildrens().remove(resultSearch.index-1);
for(int i=subNode.size()-1 ; i>=0 ; --i){
childNode.insertKey(subNode.keyAt(i), 0);
}
if(!subNode.isLeaf()){
for(int k=subNode.size() ; k>=0 ; --k){
childNode.insertChild(subNode.childAt(k),0);
}
}
}
if(root == node && node.size() == 0){
root = childNode;
}
delete(childNode, key);
}
}
}
}
编程内功修炼之数据结构—BTree(三)总结的更多相关文章
- 编程内功修炼之数据结构—BTree(一)
BTree,和二叉查找树和红黑树中一样,与关键字相联系的数据作为关键字存放在同一节点上. 一颗BTree树具有如下的特性:(根为root[T]) 1)每个节点x有以下域: (a)n[x],当前存储在节 ...
- 编程内功修炼之数据结构—BTree(二)实现BTree插入、查询、删除操作
1 package edu.algorithms.btree; import java.util.ArrayList; import java.util.List; /** * BTree类 * * ...
- Siki_Unity_3-13_编程内功修炼-算法
Unity 3-13 编程内功修炼 -- 算法 任务1&2:课程介绍 主要算法: 分治法 堆排序 二叉树 动态规划 贪心算法 图 任务3:分治算法 -- Divide and Conquer ...
- Java 内功修炼 之 数据结构与算法(一)
一.基本认识 1.数据结构与算法的关系? (1)数据结构(data structure): 数据结构指的是 数据与数据 之间的结构关系.比如:数组.队列.哈希.树 等结构. (2)算法: 算法指的是 ...
- Java 内功修炼 之 数据结构与算法(二)
一.二叉树补充.多叉树 1.二叉树(非递归实现遍历) (1)前提 前面一篇介绍了 二叉树.顺序二叉树.线索二叉树.哈夫曼树等树结构. 可参考:https://www.cnblogs.com/l-y-h ...
- Hadoop内功修炼
IT十八掌<大数据内功修炼系列课程>强势推出!由实战派名师徐培成亲自操刀,学完做不了大数据我们负全责!2015.12.21前,优惠价:4999(名额已不多!)2015.12.31前,优惠价 ...
- COJ 1003 WZJ的数据结构(三)ST表
WZJ的数据结构(三) 难度级别:B: 运行时间限制:3000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 请你设计一个数据结构,完成以下功能: 给定一个大小为N的 ...
- 我理解的数据结构(三)—— 队列(Queue)
我理解的数据结构(三)-- 队列(Queue) 一.队列 队列是一种线性结构 相比数组,队列对应的操作是数组的子集 只能从一端(队尾)添加元素,只能从另一端(队首)取出元素 队列是一种先进先出的数据结 ...
- GPU编程和流式多处理器(三)
GPU编程和流式多处理器(三) 3. Floating-Point Support 快速的本机浮点硬件是GPU的存在理由,并且在许多方面,它们在浮点实现方面都等于或优于CPU.全速支持异常可以根据每条 ...
随机推荐
- ZOJ问题--hdu3788
ZOJ问题 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- 如何设置 Internal 类,方法,属性对其他项目可见
internal 修饰符时程序集内部其他类可见.但对程序集外的类不可见,这样就很好的封装了可见性. 但是,我们也许会碰到类似的情况,特别是基于已有代码开发新的代码时,你会发现很多 internal 的 ...
- javascript事件设计模式
JavaScript事件设计模式 http://plkong.iteye.com/blog/213543 http://www.docin.com/p-696665922.html
- yum cannot retrieve metalink for repository
Error: Cannot retrieve metalink for repository: epel. Please verify its path and try again
- OC基础13:数字、字符串和集合2
"OC基础"这个分类的文章是我在自学Stephen G.Kochan的<Objective-C程序设计第6版>过程中的笔记. 17.Foundation框架的数组是有序 ...
- 吐槽下CSDN编辑器
Perface 近期喜欢上了markdown,我认为它就是一些HTML标签的快捷键,用一些符号来取代标签,易学易读易用,何乐而不为呢?近期也喜欢用印象笔记来让我的记忆永存,确实它强大的收集能力让我迷上 ...
- android初级应用到高端架构教程------ 完整体系化学习android开发
系统的学习android开发技术,从应用到底层,再到架构,告别乱糟糟的学习方式,不再是抓不住重点.从上到下贯通,全面学习android开发.让你拥有清晰的思路,一步步学习android开发! 一般而言 ...
- 如何实现在O(n)时间内排序,并且空间复杂度为O(1)
对于常见的排序算法,很难做到在O(n)时间内排序,并且空间复杂度为O(1),这里提供了一种方法可以达到要求. 可以使用哈希排序的思想,也就是将所有的数哈希到哈希表中,实现排序.具体的算法思想是,求出这 ...
- 【floyd求最小环】【Vijos 1046】【观光旅游】
标签:图结构 最短路 题目大意:给你一个无向图,至少经过3个节点的简单回路(不能包括其他环) 一开始的思路:用一个NUM[i][j]表示i到j的最短路经过几个节点,显然解法不太优美,而且还是错的 再想 ...
- vsts
首先要搞清楚啥是VSTS,这对于我们安装配置有基础作用.看看这张组织结构图就一目了然了.Visual Studio Team Suite就是我们常说的VS.NET 2005开发环境,安装包3G左右的 ...