根据算法导论用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特性。 


Java代码   收藏代码
  1. package com.btree;  
  2.   
  3. import java.util.LinkedList;  
  4. import java.util.List;  
  5.   
  6. /** 
  7.  *每个叶结点具有相同的深度。树的高度h 树的度为t 
  8.  *每个结点的关键字  非根至少t-1个,至多2t-1 个,根至少1个 
  9.  *非根非叶子结点最少t子女,最多2t个子女  
  10.  *根至少2两个子女,最多2t个子女  
  11.  *@author yuyong 2012-12-6  
  12.  *@wuhu ruixin 
  13.  */  
  14. public class BTree {  
  15.     public static Integer M=3;  
  16.     private BTreeNode root;  
  17.       
  18.     public static void main(String args[]){  
  19.         BTree tree=new BTree();  
  20.         String str="";  
  21. //      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,  
  22. //              78, 88,72, 73,81, 86, 87,91, 92, 94, 95};  
  23. //      for(int index=0;index<keys.length;index++){  
  24. //          int key=keys[index];  
  25. //          str+=key+" ";  
  26. //          tree.add(key);  
  27. //      }  
  28.         int[] keys=new int[3];  
  29.         int j=0;  
  30.         for(int i=1;i<=10000;i++){  
  31.             int key=(int) (Math.random()*100);  
  32.             if(i==10||i==24||i==30){  
  33.                 keys[j]=key;  
  34.                 j++;  
  35.             }  
  36.             tree.add(key);  
  37.         }  
  38.         tree.printTree();  
  39.         for(int key:keys){  
  40.             tree.delete(key);  
  41.             System.out.println(key);  
  42.             tree.printTree();  
  43.         }  
  44.     }  
  45.       
  46.     public void printTree(){  
  47.         String keys="";  
  48.         keys+=this.printNode(root);  
  49.         System.out.println(keys);  
  50.     }  
  51.       
  52.     public String printNode(BTreeNode node){  
  53.         String str=" \n结点:位置 "+node.position+" ";  
  54.         str+=node.keys.toString();  
  55.         if(node.sons.size()>0){  
  56.             for(BTreeNode n:node.sons){  
  57.                 str+=printNode(n);  
  58.             }  
  59.         }  
  60.         return str;  
  61.     }  
  62.       
  63.     public void add(int key){  
  64.         if(root==null){  
  65.             root=new BTreeNode(key);  
  66.             root.position=0;  
  67.             return;  
  68.         }  
  69.         this.add(root, key);  
  70.     }  
  71.       
  72.     public void add(BTreeNode node,int key){  
  73.         if(node.keys.indexOf(key)!=-1)  
  74.             return;  
  75.         if(node.keys.size()>=(2*BTree.M-1))  
  76.             node=split(node);  
  77.         int index=binarySearch(node,key);  
  78.         if(node.sons.size()>0){  
  79.             if(node.sons.get(index)!=null){  
  80.                 add(node.sons.get(index),key);  
  81.             }else  
  82.                 node.keys.add(index, key);  
  83.         }else{  
  84.             node.keys.add(index, key);  
  85.         }  
  86.     }  
  87.       
  88.     public void delete(int key){  
  89.         if(root==null)  
  90.             return;  
  91.         this.delete(root, key);  
  92.     }  
  93.       
  94.     //删除节点  
  95.     public void delete(BTreeNode node,int key){  
  96.         int index=node.keys.indexOf(key);  
  97.         if(index==-1){  
  98.             if(node.sons.size()>0){  
  99.                 index=binarySearch(node,key);  
  100.                 if(node.father!=null||node.keys.size()<(BTree.M-1)){  
  101.                     node=configKeys(node);  
  102.                     index=binarySearch(node,key);  
  103.                 }  
  104.                 delete(node.sons.get(index),key);  
  105.                   
  106.             }  
  107.         }else{  
  108.             deleteAndCombine(node,index);  
  109.         }  
  110.     }  
  111.       
  112.       
  113.     //分裂已经满关键字的节点。当向节点添加关键字的时候,如果此节点已经满关键字,则进行分裂。并且沿途分裂已经满的关键字(即使关键字不需要插入到此节点中)  
  114.     public BTreeNode split(BTreeNode node){  
  115.         if(node.keys.size()<(2*BTree.M-1))  
  116.             return node;  
  117.         int n1=BTree.M-1-1;  
  118.         int n2=n1+1;  
  119.         int n3=2*BTree.M-1-1;  
  120.         BTreeNode nodeFather=node.father;  
  121.         LinkedList<Integer> newNodesKeys=new LinkedList<Integer>();  
  122.         newNodesKeys.addAll(node.keys.subList(n2+1, n3+1));  
  123.         BTreeNode newNode=new BTreeNode(newNodesKeys);  
  124.         newNode.position=node.position+1;  
  125.         List<Integer>lists=new LinkedList<Integer>();  
  126.         lists.addAll(node.keys.subList(0, n1+1));  
  127.         if(nodeFather==null){  
  128.             nodeFather=new BTreeNode();  
  129.             nodeFather.keys.add(node.keys.get(n2));  
  130.             nodeFather.sons.add(0,node);  
  131.             newNode.father=nodeFather;  
  132.             nodeFather.sons.add(1,newNode);  
  133.             nodeFather.position=0;  
  134.             node.father=nodeFather;  
  135.             root=nodeFather;  
  136.         }else{  
  137.             nodeFather.keys.add(node.position, node.keys.get(n2));  
  138.             newNode.father=nodeFather;  
  139.             nodeFather.sons.add(node.position+1,newNode);  
  140.             for(int i=node.position+2;i<=nodeFather.sons.size()-1;i++){  
  141.                 nodeFather.sons.get(i).position=i;  
  142.             }  
  143.                   
  144.         }  
  145.         if(node.sons.size()>0){  
  146.             LinkedList<BTreeNode> newSons=new LinkedList<BTreeNode>();  
  147.             LinkedList<BTreeNode> sons=new LinkedList<BTreeNode>();  
  148.             newSons.addAll(node.sons.subList(BTree.M, 2*BTree.M));  
  149.             for(int i=0;i<=newSons.size()-1;i++){  
  150.                 newSons.get(i).position=i;  
  151.                 newSons.get(i).father=newNode;  
  152.             }  
  153.             sons.addAll(node.sons.subList(0, BTree.M));  
  154.             newNode.sons=newSons;  
  155.             node.sons.clear();  
  156.             node.sons.addAll(sons);  
  157.               
  158.         }  
  159.         node.keys.clear();  
  160.         node.keys.addAll(lists);  
  161.         return split(nodeFather);  
  162.     }  
  163.       
  164.     //合并两个节点  
  165.     public void combine(BTreeNode node1,BTreeNode node2){  
  166.         BTreeNode f=node1.father;  
  167.         if(f.sons.size()==2){  
  168.             node1.keys.addAll(f.keys);  
  169.             node1.keys.addAll(node2.keys);  
  170.             f.sons.remove(1);  
  171.             node1.father=null;  
  172.             root=node1;  
  173.         }else{  
  174.             node1.keys.add(f.keys.get(node1.position));  
  175.             node1.keys.addAll(node2.keys);  
  176.             f.keys.remove(node1.position);  
  177.             f.sons.remove(node2.position);  
  178.         }  
  179.         for(int i=node2.position;i<f.sons.size();i++)  
  180.             f.sons.get(i).position=i;  
  181.         for(int i=0,j=node1.sons.size();i<node2.sons.size();i++,j++){  
  182.             node2.sons.get(i).position=j;  
  183.             node2.sons.get(i).father=node1;  
  184.         }  
  185.         node1.sons.addAll(node2.sons);  
  186.           
  187.         configKeys(f);  
  188.           
  189.     }  
  190.       
  191.     //删除关键字,searchLeft搜到比要删除关键字大的最小关键字所在叶子节点,将此关键字和其对换,沉底到叶子节点进行删除,然后还要对叶子节点进行  
  192.     //一些符合B-tree的调整  
  193.     public void deleteAndCombine(BTreeNode node,int keyIndex) {  
  194.         if(node.sons.size()>0){  
  195.             BTreeNode left=searchLeft(node.sons.get(keyIndex+1));  
  196.             node.keys.remove(keyIndex);  
  197.             node.keys.add(keyIndex,left.keys.get(0));  
  198.             left.keys.remove(0);  
  199.             configKeys(left);  
  200.         }else{  
  201.             node.keys.remove(keyIndex);  
  202.             configKeys(node);  
  203.         }  
  204.     }  
  205.       
  206.     //搜索node子节点中最左结点  
  207.     public BTreeNode searchLeft(BTreeNode node){  
  208.         if(node.sons.size()>0){  
  209.             return searchLeft(node.sons.get(0));  
  210.         }else{  
  211.             return node;  
  212.         }  
  213.     }  
  214.       
  215.     /** 
  216.      * 避免回溯,从树根向下搜索关键字的过程中,凡是遇到途经的结点,如果该结点的关键字数是t-1, 
  217.      * 想办法从其他地方弄关键字过来,使得该结点的关键字数至少为t。 
  218.      * 考虑从相邻结点弄,如果相邻结点有的话,经过父结点进行周转。如果没有, 
  219.      * 就说明相邻结点的关键字个数也是t-1,这种情况,直接对该结点与其相邻结点进行合并,以满足要求。 
  220.      * @param node 
  221.      */  
  222.     public BTreeNode configKeys(BTreeNode node){  
  223.         if(node.keys.size()<=BTree.M-1){  
  224.             BTreeNode f=node.father;  
  225.             BTreeNode nodeRight=null;  
  226.             BTreeNode nodeLeft=null;  
  227.             if(f==null)  
  228.                 return node;  
  229.             if(node.position==0)  
  230.                 nodeRight=f.sons.get(node.position+1);  
  231.             else if(node.position==f.keys.size())  
  232.                 nodeLeft=f.sons.get(node.position-1);  
  233.             else{  
  234.                 nodeLeft=f.sons.get(node.position-1);  
  235.                 nodeRight=f.sons.get(node.position+1);  
  236.             }  
  237.               
  238.             if(nodeRight!=null&&nodeRight.keys.size()>BTree.M-1){  
  239.                 int temp=f.keys.get(node.position);  
  240.                 f.keys.remove(node.position);  
  241.                 f.keys.add(node.position, nodeRight.keys.get(0));  
  242.                 nodeRight.keys.remove(0);  
  243.                 node.keys.add(temp);  
  244.                 if(nodeRight.sons.size()>0){  
  245.                     BTreeNode n=nodeRight.sons.get(0);  
  246.                     n.position=node.sons.size();  
  247.                     n.father=node;  
  248.                     node.sons.add(n);  
  249.                     nodeRight.sons.remove(0);  
  250.                     for(int i=0;i<nodeRight.sons.size();i++)  
  251.                         nodeRight.sons.get(i).position=i;  
  252.                 }  
  253.                 return node;  
  254.             }else if(nodeLeft!=null&&nodeLeft.keys.size()>BTree.M-1){  
  255.                 int temp=f.keys.get(node.position-1);  
  256.                 f.keys.remove(node.position-1);  
  257.                 f.keys.add(node.position-1, nodeLeft.keys.get(nodeLeft.keys.size()-1));  
  258.                 nodeLeft.keys.remove(nodeLeft.keys.size()-1);  
  259.                 node.keys.add(0,temp);  
  260.                 if(nodeLeft.sons.size()>0){  
  261.                     BTreeNode n=nodeLeft.sons.get(nodeLeft.sons.size()-1);  
  262.                     n.position=0;  
  263.                     n.father=node;  
  264.                     node.sons.add(0,n);  
  265.                     for(int i=1;i<node.sons.size();i++)  
  266.                         node.sons.get(i).position=i;  
  267.                     nodeLeft.sons.remove(nodeLeft.sons.size()-1);  
  268.                 }  
  269.                 return node;  
  270.             }else{  
  271.                 if(nodeLeft!=null){  
  272.                     combine(nodeLeft,node);  
  273.                     return nodeLeft;  
  274.                 }else if(nodeRight!=null){  
  275.                     combine(node,nodeRight);  
  276.                     return node;  
  277.                 }  
  278.             }  
  279.         }  
  280.         return node;  
  281.     }  
  282.       
  283.     //二分查找  
  284.     public int binarySearch(BTreeNode node,Integer key){    
  285.         int index=0;    
  286.         if(node.keys.size()>0){    
  287.             int start=0;    
  288.             int end=node.keys.size()-1;    
  289.             int step=0;    
  290.             if(start!=end)    
  291.                 while((end-start)!=1){    
  292.                      step=(end-start)/2;    
  293.                      if(node.keys.get(start+step)>key){    
  294.                          end=end-step;    
  295.                      }else if(node.keys.get(start+step)<key){    
  296.                          start=start+step;    
  297.                      }else{    
  298.                          return start+step;    
  299.                      }    
  300.                 }    
  301.   
  302.             if(key>=node.keys.get(end)){    
  303.                 index=end+1;    
  304.             }else if(key<=node.keys.get(start)){    
  305.                 index=start;    
  306.             }else    
  307.                 index=end;    
  308.         }    
  309.         return index;  
  310.     }  
  311. }  




Java代码   收藏代码
  1. package com.btree;  
  2.   
  3. import java.util.LinkedList;  
  4. /** 
  5.  *  
  6.  *  @author yuyong 2012-12-6 
  7.  *  @wuhu ruixin 
  8.  */  
  9. public class BTreeNode {  
  10.     public BTreeNode father;  
  11.     public LinkedList<BTreeNode> sons=new LinkedList<BTreeNode>();  
  12.     public LinkedList<Integer> keys=new LinkedList<Integer>();  
  13.     public boolean leaf;  
  14.     public int position;  
  15.       
  16.     public BTreeNode(){}  
  17.       
  18.     public BTreeNode(int key){  
  19.         keys.add(key);  
  20.     }  
  21.       
  22.     public BTreeNode(LinkedList<Integer> keys){  
  23.         this.keys=keys;  
  24.     }  
  25. }  

猜你喜欢

转载自q364035622.iteye.com/blog/1902300