b tree的java实现

 1package bTree;
 2
 3import java.io.Serializable;
 4import java.util.Iterator;
 5
 6/**
 7 * Interface for a b tree
 8 * 
 9 * @author 
10 * @version 1.0
11 */

12public interface IBTree extends Serializable
13{
14    /**
15     * Method that will add an node into the b tree
16     * 
17     * @param o node to add
18     */

19    @SuppressWarnings("unchecked")
20    public void add(Comparable o);
21    
22    /**
23     * Method that will remove an node from the b tree
24     * 
25     * @param o node to remove
26     * @return object
27     */

28    @SuppressWarnings("unchecked")
29    public Object remove(Comparable o);
30    
31    /**
32     * Method that will find the element belongs to the specified node
33     * 
34     * @param o node to find
35     * @return object
36     */

37    @SuppressWarnings("unchecked")
38    public Object find(Comparable o);
39    
40    /**
41     * Method that will return an iterator of the b tree
42     * 
43     * @return the iterator of the b tree
44     */

45    @SuppressWarnings("unchecked")
46    public Iterator iterator();
47    
48    /**
49     * Method that will clear the b tree
50     */

51    public void clear();
52    
53    /**
54     * Method that will check to see if the b tree is null
55     * 
56     * @return true if the b tree is null, false if it is not
57     */

58    public boolean isEmpty();
59}

60
  1package bTree;
  2
  3import java.util.*;
  4
  5/**
  6 * @author 
  7 * @version 1.0
  8 */

  9public class BTree implements IBTree
 10{
 11    /**
 12     * Attributes
 13     */

 14    private static final long serialVersionUID = 1L;
 15    private BTreeNode root;
 16    private int order;
 17    
 18    /**
 19     * Constructor
 20     */

 21    public BTree(int order)
 22    {
 23        this.order = order;
 24        this.root = null;
 25    }

 26    
 27    /**
 28     * Constructor
 29     */

 30    public BTree()
 31    {
 32        this.order = 3;
 33        this.root = null;
 34    }

 35    /**
 36     * private class used as the tree node
 37     * 
 38     * @author 
 39     * @version 1.0
 40     */

 41    private class BTreeNode
 42    {
 43        /**
 44         * Attributes
 45         */

 46        private BTreeNode fatherNode;
 47        private ArrayList<BTreeNode> childrenNodes;
 48        @SuppressWarnings("unchecked")
 49        private ArrayList<Comparable> elements;
 50        private int order;
 51        private int position;
 52        
 53        @SuppressWarnings("unchecked")
 54        public BTreeNode(int order, Comparable element)
 55        {
 56            this.order = order;
 57            this.elements = new ArrayList<Comparable>();
 58            elements.add(element);
 59            this.childrenNodes = null;
 60            this.fatherNode = null;
 61            this.position = -1;
 62        }

 63        
 64        @SuppressWarnings("unchecked")
 65        public BTreeNode(int order)
 66        {
 67            this.order = order;
 68            this.elements = new ArrayList<Comparable>();
 69            this.childrenNodes = null;
 70            this.fatherNode = null;
 71            this.position = -1;
 72        }

 73        
 74        /**
 75         * Class attribute getter
 76         * 
 77         * @return the position
 78         */

 79        public int getPosition()
 80        {
 81            return this.position;
 82        }

 83        
 84        /**
 85         * Class attribute setter
 86         * 
 87         * @param position the position to set
 88         */

 89        public void setPosition(int position)
 90        {
 91            this.position = position;
 92        }

 93        
 94        /**
 95         * Class attribute getter
 96         * 
 97         * @return the order
 98         */

 99        public int getOrder()
100        {
101            return this.order;
102        }

103        
104        /**
105         * Class attribute setter
106         * 
107         * @param order the order to set
108         */

109        public void setOrder(int order)
110        {
111            this.order = order;
112        }

113        
114        /**
115         * Class attribute getter
116         * 
117         * @return the count
118         */

119        public int getCount()
120        {
121            return this.elements.size();
122        }

123        
124        /**
125         * Class attribute getter
126         * 
127         * @return the fatherNode
128         */

129        public BTreeNode getFatherNode()
130        {
131            return this.fatherNode;
132        }

133        
134        /**
135         * Class attribute setter
136         * 
137         * @param fatherNode the fatherNode to set
138         */

139        public void setFatherNode(BTreeNode fatherNode)
140        {
141            this.fatherNode = fatherNode;
142        }

143        
144        /**
145         * Class attribute getter
146         * 
147         * @return the childrenNodes
148         */

149        public ArrayList<BTreeNode> getChildrenNodes()
150        {
151            return this.childrenNodes;
152        }

153        
154        /**
155         * Class attribute setter
156         * 
157         * @param childrenNodes the childrenNodes to set
158         */

159        public void setChildrenNodes(ArrayList<BTreeNode> childrenNodes)
160        {
161            this.childrenNodes = childrenNodes;
162        }

163        
164        /**
165         * Class attribute getter
166         * 
167         * @return the elements
168         */

169        @SuppressWarnings("unchecked")
170        public ArrayList<Comparable> getElements()
171        {
172            return this.elements;
173        }

174        
175        /**
176         * Class attribute setter
177         * 
178         * @param elements the elements to set
179         */

180        @SuppressWarnings("unchecked")
181        public void setElements(ArrayList<Comparable> elements)
182        {
183            this.elements = elements;
184        }

185    }

186    
187    /*
188     * (non-Javadoc)
189     * 
190     * @see bTree.IBTree#add(java.lang.Comparable)
191     */

192    @SuppressWarnings("unchecked")
193    @Override
194    public void add(Comparable o)
195    {
196        Object object = find(o);
197        if(object != null)
198        {
199            return;
200        }

201        if(this.root == null)// first element
202        {
203            BTreeNode btn = new BTreeNode(this.order, o);
204            this.root = btn;
205        }

206        else
207        // more than one element
208        {
209            addToLeaf(this.root, o);
210        }

211    }

212    
213    @SuppressWarnings("unchecked")
214    private void split(BTreeNode btn)// when sub nodes and elements are
215    // already properly placed
216    {
217        BTreeNode fatherNode = btn.getFatherNode();// get its father
218        // node
219        int pointer = 0;
220        BTreeNode leftBranch = new BTreeNode(btn.getOrder());
221        BTreeNode rightBranch = new BTreeNode(btn.getOrder());
222        while(pointer < btn.getOrder())
223        {
224            leftBranch.getElements().add(btn.getElements().get(pointer));
225            pointer++;
226        }

227        pointer++;
228        while(pointer < btn.getOrder() * 2 + 1)
229        {
230            rightBranch.getElements().add(btn.getElements().get(pointer));
231            pointer++;
232        }

233        if(btn.getChildrenNodes() != null)// not leaf
234        {
235            pointer = 0;
236            ArrayList<BTreeNode> leftChildren = new ArrayList<BTreeNode>();
237            while(pointer <= btn.getOrder())
238            {
239                BTreeNode child = btn.getChildrenNodes().get(pointer);
240                leftChildren.add(child);
241                child.setPosition(pointer);
242                child.setFatherNode(leftBranch);
243                pointer++;
244            }

245            leftBranch.setChildrenNodes(leftChildren);
246            ArrayList<BTreeNode> rightChildren = new ArrayList<BTreeNode>();
247            while(pointer <= btn.getOrder() * 2 + 1)
248            {
249                BTreeNode child = btn.getChildrenNodes().get(pointer);
250                rightChildren.add(child);
251                child.setPosition(pointer - btn.getOrder() - 1);
252                child.setFatherNode(rightBranch);
253                pointer++;
254            }

255            rightBranch.setChildrenNodes(rightChildren);
256        }

257        if(fatherNode == null)// reached the root
258        {
259            BTreeNode newNode = new BTreeNode(btn.getOrder());
260            newNode.getElements().add(btn.getElements().get(btn.getOrder()));
261            ArrayList<BTreeNode> children = new ArrayList<BTreeNode>();
262            children.add(leftBranch);
263            children.add(rightBranch);
264            leftBranch.setFatherNode(newNode);
265            rightBranch.setFatherNode(newNode);
266            leftBranch.setPosition(0);
267            rightBranch.setPosition(1);
268            newNode.setChildrenNodes(children);
269            this.root = newNode;
270        }

271        else
272        // not the root
273        {
274            ArrayList<Comparable> currentElements = fatherNode.getElements();
275            if(btn.getPosition() == btn.getOrder() * 2)
276            {
277                currentElements.add(btn.getElements().get(btn.getOrder()));
278                fatherNode.getChildrenNodes().remove(btn.getPosition());
279                fatherNode.getChildrenNodes().add(leftBranch);
280                fatherNode.getChildrenNodes().add(rightBranch);
281                leftBranch.setFatherNode(fatherNode);
282                rightBranch.setFatherNode(fatherNode);
283                for(int i = 0; i < fatherNode.getChildrenNodes().size(); i++)
284                {
285                    fatherNode.getChildrenNodes().get(i).setPosition(i);
286                }

287            }

288            else
289            {
290                currentElements.add(btn.getPosition(), btn.getElements().get(
291                        btn.getOrder()));
292                fatherNode.getChildrenNodes().remove(btn.getPosition());
293                fatherNode.getChildrenNodes()
294                        .add(btn.getPosition(), leftBranch);
295                fatherNode.getChildrenNodes().add(btn.getPosition() + 1,
296                        rightBranch);
297                leftBranch.setFatherNode(fatherNode);
298                rightBranch.setFatherNode(fatherNode);
299                for(int i = 0; i < fatherNode.getChildrenNodes().size(); i++)
300                {
301                    fatherNode.getChildrenNodes().get(i).setPosition(i);
302                }

303            }

304        }

305    }

306    
307    private void checkAndSplit(BTreeNode btn)
308    {
309        if(btn.getCount() >= btn.getOrder() * 2 + 1)// need to split
310        {
311            split(btn);
312            if(btn.getFatherNode() != null)
313            {
314                checkAndSplit(btn.getFatherNode());
315            }

316        }

317    }

318    
319    @SuppressWarnings("unchecked")
320    private void addToLeaf(BTreeNode btn, Comparable o)
321    {
322        if(btn.getElements().contains(o))
323        {
324            return;
325        }

326        if(btn.getChildrenNodes() == null)// leaf
327        {
328            btn.getElements().add(o);
329            Collections.sort(btn.getElements());// sort the elements in the
330            // leaf
331            checkAndSplit(btn);
332        }

333        else
334        // not leaf, add to its proper sub node
335        {
336            int pointer = 0;
337            while(pointer < btn.getElements().size())
338            {
339                if(o.compareTo(btn.getElements().get(pointer)) < 0)// found it
340                {
341                    break;
342                }

343                pointer++;
344            }

345            addToLeaf(btn.getChildrenNodes().get(pointer), o);
346        }

347    }

348    
349    @SuppressWarnings("unchecked")
350    private Object findNode(BTreeNode btn, Comparable o)
351    {
352        int index = -1;
353        ArrayList<Comparable> al = btn.getElements();
354        for(int i = 0; i < al.size(); i++)
355        {
356            if(o.compareTo(al.get(i)) == 0)
357            {
358                index = i;
359                break;
360            }

361        }

362        if(index == -1)// can not find it
363        {
364            if(btn.getChildrenNodes() == null)// leaf
365            {
366                return null;
367            }

368            else
369            // not leaf, add to its proper sub node
370            {
371                int pointer = 0;
372                while(pointer < btn.getElements().size())
373                {
374                    if(o.compareTo(btn.getElements().get(pointer)) < 0)// found
375                    // it's sub node
376                    {
377                        break;
378                    }

379                    pointer++;
380                }

381                return findNode(btn.getChildrenNodes().get(pointer), o);
382            }

383        }

384        else
385        {
386            return btn.getElements().get(index);
387        }

388    }

389    
390    /*
391     * (non-Javadoc)
392     * 
393     * @see bTree.IBTree#find(java.lang.Comparable)
394     */

395    @SuppressWarnings("unchecked")
396    @Override
397    public Object find(Comparable o)
398    {
399        if(this.root == null)
400        {
401            return null;
402        }

403        else
404        {
405            return findNode(this.root, o);
406        }

407    }

408    
409    /*
410     * (non-Javadoc)
411     * 
412     * @see bTree.IBTree#iterator()
413     */

414    @SuppressWarnings("unchecked")
415    @Override
416    public Iterator iterator()
417    {
418        ArrayList<Comparable> al = new ArrayList<Comparable>();
419        fill(al, this);
420        return al.iterator();
421    }

422    
423    @SuppressWarnings("unchecked")
424    private void fill(ArrayList<Comparable> al, BTree bt)
425    {
426        if(bt.root == null)
427        {
428            return;
429        }

430        fill(al, bt.root);
431    }

432    
433    @SuppressWarnings("unchecked")
434    private void fill(ArrayList<Comparable> al, BTreeNode btn)
435    {
436        if(btn.getChildrenNodes() == null)// leaf
437        {
438            for(int i = 0; i < btn.getElements().size(); i++)
439            {
440                al.add(btn.getElements().get(i));
441            }

442        }

443        else
444        {
445            int pointer = 0;
446            while(pointer < btn.getElements().size())
447            {
448                fill(al, btn.getChildrenNodes().get(pointer));
449                al.add(btn.getElements().get(pointer));
450                pointer++;
451            }

452            fill(al, btn.getChildrenNodes().get(pointer));
453        }

454    }

455    
456    /*
457     * (non-Javadoc)
458     * 
459     * @see bTree.IBTree#remove(java.lang.Comparable)
460     */

461    @SuppressWarnings("unchecked")
462    @Override
463    public Object remove(Comparable o)
464    {
465        if(this.root == null)
466        {
467            return null;
468        }

469        Container original = new Container();
470        findOriginalNode(this.root, o, original);
471        if(original.getBtn() == null)
472        {
473            return null;
474        }

475        Object object = original.getBtn().getElements().get(
476                original.getPosition());
477        if(original.getBtn().getChildrenNodes() == null)// leaf,no need to swap
478        {
479            deleteOneElementFromTheLeaf(original);
480        }

481        else
482        // not leaf,swap them,then delete the one at leaf
483        {
484            Container smallest = new Container();
485            findSmallestNode(original.getBtn().getChildrenNodes().get(
486                    original.getPosition() + 1), smallest);
487            // swap them
488            Comparable temp = original.getBtn().getElements().get(
489                    original.getPosition());
490            original.getBtn().getElements()
491                    .set(
492                            original.getPosition(),
493                            smallest.getBtn().getElements().get(
494                                    smallest.getPosition()));
495            smallest.getBtn().getElements().set(smallest.getPosition(), temp);
496            deleteOneElementFromTheLeaf(smallest);
497        }

498        return object;
499    }

500    
501    @SuppressWarnings("unchecked")
502    private void deleteOneElementFromTheLeaf(Container c)
503    {
504        BTreeNode btn = c.getBtn();
505        if(btn.getElements().size() <= btn.getOrder())// less than order+1,
506        {
507            BTreeNode fatherNode = btn.getFatherNode();
508            if(fatherNode == null)// it is also root
509            {
510                if(btn.getElements().size() == 1)
511                {
512                    this.root = null;
513                }

514                else
515                {
516                    btn.getElements().remove(c.getPosition());
517                }

518                return;
519            }

520            else
521            {
522                if(fatherNode.getElements().size() == 1)// only one element,need
523                // grand
524                {
525                    Comparable add = fatherNode.getElements().get(0);
526                    BTreeNode grandNode = fatherNode.getFatherNode();
527                    if(grandNode == null)// father node is the root
528                    {
529                        if(btn.getPosition() == 0)// other side is at position
530                        // 1
531                        {
532                            fatherNode.getChildrenNodes().get(1).setFatherNode(
533                                    null);
534                            fatherNode.getChildrenNodes().get(1)
535                                    .setPosition(-1);
536                            this.root = fatherNode.getChildrenNodes().get(1);
537                            addToLeaf(this.root, add);
538                            btn.getElements().remove(c.getPosition());
539                            for(int i = 0; i < btn.getElements().size(); i++)
540                            {
541                                addToLeaf(this.root, btn.getElements().get(i));
542                            }

543                        }

544                        else
545                        // other side is at position 0
546                        {
547                            fatherNode.getChildrenNodes().get(0).setFatherNode(
548                                    null);
549                            fatherNode.getChildrenNodes().get(0)
550                                    .setPosition(-1);
551                            this.root = fatherNode.getChildrenNodes().get(0);
552                            addToLeaf(this.root, add);
553                            btn.getElements().remove(c.getPosition());
554                            for(int i = 0; i < btn.getElements().size(); i++)
555                            {
556                                addToLeaf(this.root, btn.getElements().get(i));
557                            }

558                        }

559                    }

560                    else
561                    // father node is not the root
562                    {
563                        if(btn.getPosition() == 0)// other side is at position
564                        // 1
565                        {
566                            fatherNode.getChildrenNodes().get(1).setFatherNode(
567                                    grandNode);
568                            fatherNode.getChildrenNodes().get(1).setPosition(
569                                    fatherNode.getPosition());
570                            grandNode.getChildrenNodes().set(
571                                    fatherNode.getPosition(),
572                                    fatherNode.getChildrenNodes().get(1));
573                            addToLeaf(this.root, add);
574                            btn.getElements().remove(c.getPosition());
575                            for(int i = 0; i < btn.getElements().size(); i++)
576                            {
577                                addToLeaf(this.root, btn.getElements().get(i));
578                            }

579                        }

580                        else
581                        // other side is at position 0
582                        {
583                            fatherNode.getChildrenNodes().get(0).setFatherNode(
584                                    grandNode);
585                            fatherNode.getChildrenNodes().get(0).setPosition(
586                                    fatherNode.getPosition());
587                            grandNode.getChildrenNodes().set(
588                                    fatherNode.getPosition(),
589                                    fatherNode.getChildrenNodes().get(0));
590                            addToLeaf(this.root, add);
591                            btn.getElements().remove(c.getPosition());
592                            for(int i = 0; i < btn.getElements().size(); i++)
593                            {
594                                addToLeaf(this.root, btn.getElements().get(i));
595                            }

596                        }

597                    }

598                }

599                else
600                // don't need grand
601                {
602                    if(btn.getPosition() == 0)
603                    {
604                        Comparable add = fatherNode.getElements().get(0);
605                        fatherNode.getElements().remove(0);
606                        fatherNode.getChildrenNodes().remove(0);
607                        addToLeaf(this.root, add);
608                        btn.getElements().remove(c.getPosition());
609                        for(int i = 0; i < btn.getElements().size(); i++)
610                        {
611                            addToLeaf(this.root, btn.getElements().get(i));
612                        }

613                    }

614                    else
615                    {
616                        Comparable add = fatherNode.getElements().get(
617                                btn.getPosition() - 1);
618                        fatherNode.getElements().remove(btn.getPosition() - 1);
619                        fatherNode.getChildrenNodes().remove(btn.getPosition());
620                        addToLeaf(this.root, add);
621                        btn.getElements().remove(c.getPosition());
622                        for(int i = 0; i < btn.getElements().size(); i++)
623                        {
624                            addToLeaf(this.root, btn.getElements().get(i));
625                        }

626                    }

627                }

628            }

629        }

630        else
631        // many elements left,just delete the one
632        {
633            btn.getElements().remove(c.getPosition());
634        }

635    }

636    
637    @SuppressWarnings("unchecked")
638    private void findOriginalNode(BTreeNode btn, Comparable o, Container c)
639    {
640        int index = btn.getElements().indexOf(o);
641        if(index == -1)// can not find it
642        {
643            if(btn.getChildrenNodes() == null)// leaf
644            {
645                return;
646            }

647            else
648            // not leaf
649            {
650                int pointer = 0;
651                while(pointer < btn.getElements().size())
652                {
653                    if(o.compareTo(btn.getElements().get(pointer)) < 0)// found
654                    // it's sub node
655                    {
656                        break;
657                    }

658                    pointer++;
659                }

660                findOriginalNode(btn.getChildrenNodes().get(pointer), o, c);
661            }

662        }

663        else
664        {
665            c.setBtn(btn);
666            c.setPosition(index);
667        }

668    }

669    
670    private void findSmallestNode(BTreeNode btn, Container c)
671    {
672        if(btn.getChildrenNodes() == null)// leaf
673        {
674            c.setBtn(btn);
675            c.setPosition(0);
676        }

677        else
678        // not leaf
679        {
680            findSmallestNode(btn.getChildrenNodes().get(0), c);
681        }

682    }

683    /**
684     * Because JAVA doesn't support the useful keywords for parameters: in ref
685     * out(C#) byval byref (VB.NET), have to make an internal class to do it
686     * 
687     * @author 
688     * @version 1.0
689     */

690    private class Container
691    {
692        private BTreeNode btn;
693        private int position;
694        
695        /**
696         * Class attribute getter
697         * 
698         * @return the btn
699         */

700        public BTreeNode getBtn()
701        {
702            return this.btn;
703        }

704        
705        /**
706         * Class attribute setter
707         * 
708         * @param btn the btn to set
709         */

710        public void setBtn(BTreeNode btn)
711        {
712            this.btn = btn;
713        }

714        
715        /**
716         * Class attribute getter
717         * 
718         * @return the position
719         */

720        public int getPosition()
721        {
722            return this.position;
723        }

724        
725        /**
726         * Class attribute setter
727         * 
728         * @param position the position to set
729         */

730        public void setPosition(int position)
731        {
732            this.position = position;
733        }

734    }

735    
736    /**
737     * Class attribute getter
738     * 
739     * @return the order
740     */

741    public int getOrder()
742    {
743        return this.order;
744    }

745    
746    /*
747     * (non-Javadoc)
748     * 
749     * @see bTree.IBTree#clear()
750     */

751    @Override
752    public void clear()
753    {
754        this.root = null;
755    }

756    
757    /*
758     * (non-Javadoc)
759     * 
760     * @see bTree.IBTree#isEmpty()
761     */

762    @Override
763    public boolean isEmpty()
764    {
765        return this.root == null;
766    }

767}

768
posted @ 2007-12-03 06:41  N/A2011  阅读(3091)  评论(0编辑  收藏  举报