`
猫不吃的鱼
  • 浏览: 159052 次
  • 性别: Icon_minigender_1
  • 来自: 芜湖市
社区版块
存档分类
最新评论

根据算法导论用java实现的b-tree

阅读更多
B-tree(多路搜索树),数据结构的一种,使用B-tree结构可以显著减少定位记录时所经历的中间过程,从而加快存取速度。

算法导论18章介绍的B-TREE 特性:
1、每个叶结点具有相同的深度。
2、假如树的度为T(子节点数),则根节点的关键字最少1个,最多2t-1个,非根节点,最少
t-1个,最多2t-1个。
3、根最少2个子节点,最多2t个子节点,非根非叶子节点,至少t个子节点,最多2t个子女。

添加和删除思路:
  添加:
   当向一个节点添加关键字的时候,如果此节点关键字已饱和,则需要分裂,并且此分裂会向上层传递,因为上层可能也饱和,分裂到上层的关键字需要在上层分裂之后再插入。
    所以,可以考虑,插入节点的时候,从根部到目的节点,沿途遇到饱和的节点就进行分裂。可以避免回溯。

  删除:
  从根到目的节点沿途节点,遇到不大于t-1的节点时,则从兄弟节点弄关键字名额(经过父节点转换),如果兄弟节点也是不大于t-1,则进行合并。
  把要删除的关键字沉降到叶子节点,和叶子节点上大于目标关键字的最小关键字进行位置交换,将目标关键字转移到叶子节点进行删除,然后还需要对此叶子节点进行调整以符合B-TREE特性。


package com.btree;

import java.util.LinkedList;
import java.util.List;

/**
 *每个叶结点具有相同的深度。树的高度h 树的度为t
 *每个结点的关键字  非根至少t-1个,至多2t-1 个,根至少1个
 *非根非叶子结点最少t子女,最多2t个子女 
 *根至少2两个子女,最多2t个子女 
 *@author yuyong 2012-12-6 
 *@wuhu ruixin
 */
public class BTree {
	public static Integer M=3;
	private BTreeNode root;
	
	public static void main(String args[]){
		BTree tree=new BTree();
		String str="";
//		int[] keys=new int[]{71,10, 14, 31, 54,3, 4, 5,11, 12,15, 23, 25, 27,32, 35, 40, 43, 48,55, 57, 63, 67, 68,
//				78, 88,72, 73,81, 86, 87,91, 92, 94, 95};
//		for(int index=0;index<keys.length;index++){
//			int key=keys[index];
//			str+=key+" ";
//			tree.add(key);
//		}
		int[] keys=new int[3];
		int j=0;
		for(int i=1;i<=10000;i++){
			int key=(int) (Math.random()*100);
			if(i==10||i==24||i==30){
				keys[j]=key;
				j++;
			}
			tree.add(key);
		}
		tree.printTree();
		for(int key:keys){
			tree.delete(key);
			System.out.println(key);
			tree.printTree();
		}
	}
	
	public void printTree(){
		String keys="";
		keys+=this.printNode(root);
		System.out.println(keys);
	}
	
	public String printNode(BTreeNode node){
		String str=" \n结点:位置 "+node.position+" ";
		str+=node.keys.toString();
		if(node.sons.size()>0){
			for(BTreeNode n:node.sons){
				str+=printNode(n);
			}
		}
		return str;
	}
	
	public void add(int key){
		if(root==null){
			root=new BTreeNode(key);
			root.position=0;
			return;
		}
		this.add(root, key);
	}
	
	public void add(BTreeNode node,int key){
		if(node.keys.indexOf(key)!=-1)
			return;
		if(node.keys.size()>=(2*BTree.M-1))
			node=split(node);
		int index=binarySearch(node,key);
		if(node.sons.size()>0){
			if(node.sons.get(index)!=null){
				add(node.sons.get(index),key);
			}else
				node.keys.add(index, key);
		}else{
			node.keys.add(index, key);
		}
	}
	
	public void delete(int key){
		if(root==null)
			return;
		this.delete(root, key);
	}
	
	//删除节点
	public void delete(BTreeNode node,int key){
		int index=node.keys.indexOf(key);
		if(index==-1){
			if(node.sons.size()>0){
				index=binarySearch(node,key);
				if(node.father!=null||node.keys.size()<(BTree.M-1)){
					node=configKeys(node);
					index=binarySearch(node,key);
				}
				delete(node.sons.get(index),key);
				
			}
		}else{
			deleteAndCombine(node,index);
		}
	}
	
	
	//分裂已经满关键字的节点。当向节点添加关键字的时候,如果此节点已经满关键字,则进行分裂。并且沿途分裂已经满的关键字(即使关键字不需要插入到此节点中)
	public BTreeNode split(BTreeNode node){
		if(node.keys.size()<(2*BTree.M-1))
			return node;
		int n1=BTree.M-1-1;
		int n2=n1+1;
		int n3=2*BTree.M-1-1;
		BTreeNode nodeFather=node.father;
		LinkedList<Integer> newNodesKeys=new LinkedList<Integer>();
		newNodesKeys.addAll(node.keys.subList(n2+1, n3+1));
		BTreeNode newNode=new BTreeNode(newNodesKeys);
		newNode.position=node.position+1;
        List<Integer>lists=new LinkedList<Integer>();
        lists.addAll(node.keys.subList(0, n1+1));
        if(nodeFather==null){
			nodeFather=new BTreeNode();
			nodeFather.keys.add(node.keys.get(n2));
			nodeFather.sons.add(0,node);
			newNode.father=nodeFather;
			nodeFather.sons.add(1,newNode);
			nodeFather.position=0;
			node.father=nodeFather;
			root=nodeFather;
		}else{
			nodeFather.keys.add(node.position, node.keys.get(n2));
			newNode.father=nodeFather;
			nodeFather.sons.add(node.position+1,newNode);
			for(int i=node.position+2;i<=nodeFather.sons.size()-1;i++){
				nodeFather.sons.get(i).position=i;
			}
				
		}
        if(node.sons.size()>0){
        	LinkedList<BTreeNode> newSons=new LinkedList<BTreeNode>();
        	LinkedList<BTreeNode> sons=new LinkedList<BTreeNode>();
        	newSons.addAll(node.sons.subList(BTree.M, 2*BTree.M));
        	for(int i=0;i<=newSons.size()-1;i++){
        		newSons.get(i).position=i;
        		newSons.get(i).father=newNode;
        	}
        	sons.addAll(node.sons.subList(0, BTree.M));
        	newNode.sons=newSons;
        	node.sons.clear();
        	node.sons.addAll(sons);
        	
        }
        node.keys.clear();
        node.keys.addAll(lists);
        return split(nodeFather);
	}
	
	//合并两个节点
	public void combine(BTreeNode node1,BTreeNode node2){
		BTreeNode f=node1.father;
		if(f.sons.size()==2){
			node1.keys.addAll(f.keys);
			node1.keys.addAll(node2.keys);
			f.sons.remove(1);
			node1.father=null;
			root=node1;
		}else{
			node1.keys.add(f.keys.get(node1.position));
			node1.keys.addAll(node2.keys);
			f.keys.remove(node1.position);
			f.sons.remove(node2.position);
		}
		for(int i=node2.position;i<f.sons.size();i++)
			f.sons.get(i).position=i;
		for(int i=0,j=node1.sons.size();i<node2.sons.size();i++,j++){
			node2.sons.get(i).position=j;
			node2.sons.get(i).father=node1;
		}
		node1.sons.addAll(node2.sons);
		
		configKeys(f);
		
	}
	
	//删除关键字,searchLeft搜到比要删除关键字大的最小关键字所在叶子节点,将此关键字和其对换,沉底到叶子节点进行删除,然后还要对叶子节点进行
	//一些符合B-tree的调整
	public void deleteAndCombine(BTreeNode node,int keyIndex) {
		if(node.sons.size()>0){
			BTreeNode left=searchLeft(node.sons.get(keyIndex+1));
			node.keys.remove(keyIndex);
			node.keys.add(keyIndex,left.keys.get(0));
			left.keys.remove(0);
			configKeys(left);
		}else{
			node.keys.remove(keyIndex);
			configKeys(node);
		}
	}
	
	//搜索node子节点中最左结点
	public BTreeNode searchLeft(BTreeNode node){
		if(node.sons.size()>0){
			return searchLeft(node.sons.get(0));
		}else{
			return node;
		}
	}
	
	/**
	 * 避免回溯,从树根向下搜索关键字的过程中,凡是遇到途经的结点,如果该结点的关键字数是t-1,
	 * 想办法从其他地方弄关键字过来,使得该结点的关键字数至少为t。
     * 考虑从相邻结点弄,如果相邻结点有的话,经过父结点进行周转。如果没有,
     * 就说明相邻结点的关键字个数也是t-1,这种情况,直接对该结点与其相邻结点进行合并,以满足要求。
	 * @param node
	 */
	public BTreeNode configKeys(BTreeNode node){
		if(node.keys.size()<=BTree.M-1){
			BTreeNode f=node.father;
			BTreeNode nodeRight=null;
			BTreeNode nodeLeft=null;
			if(f==null)
				return node;
			if(node.position==0)
				nodeRight=f.sons.get(node.position+1);
			else if(node.position==f.keys.size())
				nodeLeft=f.sons.get(node.position-1);
			else{
				nodeLeft=f.sons.get(node.position-1);
				nodeRight=f.sons.get(node.position+1);
			}
			
			if(nodeRight!=null&&nodeRight.keys.size()>BTree.M-1){
				int temp=f.keys.get(node.position);
				f.keys.remove(node.position);
				f.keys.add(node.position, nodeRight.keys.get(0));
				nodeRight.keys.remove(0);
				node.keys.add(temp);
				if(nodeRight.sons.size()>0){
					BTreeNode n=nodeRight.sons.get(0);
					n.position=node.sons.size();
					n.father=node;
					node.sons.add(n);
					nodeRight.sons.remove(0);
					for(int i=0;i<nodeRight.sons.size();i++)
						nodeRight.sons.get(i).position=i;
				}
				return node;
			}else if(nodeLeft!=null&&nodeLeft.keys.size()>BTree.M-1){
				int temp=f.keys.get(node.position-1);
				f.keys.remove(node.position-1);
				f.keys.add(node.position-1, nodeLeft.keys.get(nodeLeft.keys.size()-1));
				nodeLeft.keys.remove(nodeLeft.keys.size()-1);
				node.keys.add(0,temp);
				if(nodeLeft.sons.size()>0){
					BTreeNode n=nodeLeft.sons.get(nodeLeft.sons.size()-1);
					n.position=0;
					n.father=node;
					node.sons.add(0,n);
					for(int i=1;i<node.sons.size();i++)
						node.sons.get(i).position=i;
					nodeLeft.sons.remove(nodeLeft.sons.size()-1);
				}
				return node;
			}else{
				if(nodeLeft!=null){
					combine(nodeLeft,node);
					return nodeLeft;
				}else if(nodeRight!=null){
					combine(node,nodeRight);
					return node;
				}
			}
		}
		return node;
	}
	
	//二分查找
	public int binarySearch(BTreeNode node,Integer key){  
        int index=0;  
        if(node.keys.size()>0){  
            int start=0;  
            int end=node.keys.size()-1;  
            int step=0;  
            if(start!=end)  
                while((end-start)!=1){  
                     step=(end-start)/2;  
                     if(node.keys.get(start+step)>key){  
                         end=end-step;  
                     }else if(node.keys.get(start+step)<key){  
                         start=start+step;  
                     }else{  
                         return start+step;  
                     }  
                }  

            if(key>=node.keys.get(end)){  
                index=end+1;  
            }else if(key<=node.keys.get(start)){  
                index=start;  
            }else  
                index=end;  
        }  
        return index;
	}
}






package com.btree;

import java.util.LinkedList;
/**
 * 
 *  @author yuyong 2012-12-6
 *  @wuhu ruixin
 */
public class BTreeNode {
	public BTreeNode father;
	public LinkedList<BTreeNode> sons=new LinkedList<BTreeNode>();
	public LinkedList<Integer> keys=new LinkedList<Integer>();
	public boolean leaf;
	public int position;
	
	public BTreeNode(){}
	
	public BTreeNode(int key){
		keys.add(key);
	}
	
	public BTreeNode(LinkedList<Integer> keys){
		this.keys=keys;
	}
}



代码写的比较丑,还望海涵
1
1
分享到:
评论
1 楼 shliujing 2016-08-09  
good!!!

相关推荐

    详解python实现FP-TREE进行关联规则挖掘

    本文将深入探讨如何使用Python来实现FP-TREE算法,并通过Python3.2进行演示。为了可视化FP树的生成过程,需要安装PIL库来处理图像。 首先,我们需要理解关联规则挖掘的基本概念。关联规则通常由两部分组成:前提...

    基于R-Tree的DBSCAN算法的改进(Java版)

    实现基于R-Tree的DBSCAN算法,开发者可以利用Java的库,如JTS(Java Topology Suite)或GeoTools,它们提供了R-Tree的实现,并且与地理空间数据操作兼容。 在"DBSCAN_06"这个文件中,可能包含了以下内容: 1. R-...

    fp-tree算法程序

    下面将详细解释FP-Tree算法的核心原理及其在C#中的实现。 **FP-Tree算法概述:** FP-Tree算法由Han等人于2000年提出,主要用于关联规则学习。它的主要目的是通过构建一棵特殊的树结构(FP-Tree)来降低内存消耗和...

    详解Java实现的k-means聚类算法

    在Java中实现k-means聚类算法需要使用到以下几个重要的概念: 1. ArrayList:ArrayList是Java中的一种集合类型,用于存储数据点。 2. Map:Map是Java中的一种集合类型,用于存储质心和簇的对应关系。 3. SQL:SQL是...

    算法导论中算法的java实现

    在这个主题下,我们将探讨如何将书中的算法用Java语言进行实现,以及如何通过源码和工具来理解和学习这些算法。 在Java中实现《算法导论》中的算法,首先需要理解算法的基本思想和逻辑结构。这包括排序算法(如冒泡...

    算法导论 - Thomas

    通过上述总结可以看出,《算法导论》(第三版)是一本全面介绍了算法理论与实践的教材,涵盖了算法的基础知识、设计技巧、分析方法以及具体的应用实例。适合于计算机科学领域的学生、研究人员以及从业者学习参考。

    用Borland C写的B-Tree算法.zip

    这个压缩包“用Borland C写的B-Tree算法.zip”显然包含了一个使用Borland C编译器实现的B-Tree算法源代码,这为我们提供了学习和理解B-Tree工作原理的一个实用示例。 Borland C++是Borland公司推出的一款早期的C++...

    fp-tree java源码

    ### FP-Tree算法详解及其Java源码实现 在数据挖掘领域,尤其是关联规则挖掘中,寻找频繁模式是一项核心任务。传统的Apriori算法虽然有效,但因需多次扫描数据库而存在效率瓶颈。针对这一问题,韩嘉炜教授提出的FP-...

    上学时 一些算法导论的代码----

    这些文件名揭示了几个经典的计算机科学算法,它们都是在学习《算法导论》时常见的实践练习。下面将分别介绍这些算法及其应用。 1. **矩阵连乘**: 矩阵连乘是线性代数中的一个基本问题,涉及到计算两个或多个矩阵的...

    FP-TREE算法 C++实现

    这个C++实现版本提供了FP-TREE算法的完整功能,包括构建FP树、查找频繁项集以及进行关联规则挖掘。 在数据挖掘中,频繁项集是指在数据集中出现次数超过预设阈值的项集合。FP-TREE算法通过构建一棵特殊的树结构来...

    算法导论三新增章节---

    在IT领域,特别是计算机科学与技术专业中,《算法导论》(Introduction to Algorithms)是一部备受推崇的经典教材,由Thomas H. Cormen、Charles E. Leiserson、Ronald L. Rivest和Clifford Stein四位作者共同编写。...

    算法导论(英文版)-算法导论(英文版)

    算法导论 the introduction to algorithm MIT(两个分卷) 算法导论 the introduction to algorithm MIT(两个分卷) 算法导论 the introduction to algorithm MIT(两个分卷) 算法导论 the introduction to algorithm ...

    算法导论_java_

    《算法导论》是计算机科学领域的一本经典著作,它深入浅出地介绍了算法的设计、分析和实现。这本书广泛应用于大学计算机科学课程中,对于学习和理解算法有着极高的价值。在Java编程环境下,我们可以利用Java语言来...

    算法导论习题答案13.3-1

    算法导论习题答案13.3-1,需要安装OpenOffice 打开。

    算法导论习题答案---关于算法习题的答案

    《算法导论》是计算机科学领域的一本经典著作,它深入浅出地介绍了算法的设计、分析和实现。这本书涵盖了从基础的数据结构到高级的算法分析,对于学习和理解算法有着极高的价值。习题是书中的重要组成部分,它们旨在...

    中科大算法导论答案1-13次全部 中科大算法导论答案1-13次全部

    中科大算法导论答案1-13次全部 中科大算法导论答案1-13次全部 中科大算法导论答案1-13次全部 中科大算法导论答案1-13次全部 中科大算法导论答案1-13次全部 中科大算法导论答案1-13次全部

    算法导论第15章课后习题答案

    算法导论第15章-动态规划的课后习题参考答案,对于算法爱好者而言,是不错的参考资料。

    simhash算法的java实现simhash-java.zip

    simhash 算法的 java 实现。特点计算字符串的 simhash通过构建智能索引来计算所有字符串之间的相似性,因此可以处理大数据使用使用输入文件和输出文件运行 Maininputfile 的格式(参见 src / test_in):一个文件每...

Global site tag (gtag.js) - Google Analytics