zoukankan      html  css  js  c++  java
  • B树

    package org.riley.tree;
    
    import java.util.Random;
    
    /**
     * 保存int的集合 集合中的元素存放在B-树中
     * 
     * @author dou
     * 
     */
    public class IntBalancedSet implements Cloneable 
    {
        private static final int MINIMUM = 2;// 非根节点中最少存放的元素个数
        private static final int MAXIMUM = 2 * MINIMUM;// 节点中最多存放的元素个数
        int dataCount;// 存放节点中元素的个数
        int[] data;
        int childCount;// 存放节点中子树的个数
        IntBalancedSet[] subset;
    
        /**
         * 为数组提供额外的空间,方便对数组进行删除和添加操作
         */
        public IntBalancedSet() 
        {
            data = new int[MAXIMUM + 1];
            subset = new IntBalancedSet[MAXIMUM + 2];
        }
    
        /**
         * 在集合中添加新元素
         * 
         * @param element
         */
        public void add(int element) 
        {
            looseAdd(element);
            /*
             * 如果根节点比MAXIMUM大时,将根节点复制给一个新节点.并清空根节点.将新节点作为个根节点的 子树节点.再对此子节点进行拆分.
             * B-数只在根节点处才能增加高度
             */
            if (dataCount > MAXIMUM) {
                IntBalancedSet cpy = copyData();
                data = new int[MAXIMUM + 1];
                dataCount = 0;
                childCount = dataCount + 1;
                subset = new IntBalancedSet[MAXIMUM + 2];
                subset[0] = cpy;
                fixExcess(0);
            }
        }
    
        /**
         * B-树是有效的的前提下,可以调用此方法. 如果elememt在集合中存在.那么集合不变.否则,该元素添加到集合中.并且集合的根节点元素
         * 数目允许比MAXIMUM大1
         * 
         * @param element
         */
        private void looseAdd(int element) 
        {
            int i = firstGE(element);
            if (i == dataCount) {
                if (childCount == 0) {
                    insertEle(element, i);
                } else {
                    subset[i].looseAdd(element);
                    fixExcess(i);
                }
            } else {
                if (data[i] == element) {
                    return;
                } else {
                    if (childCount == 0) {
                        insertEle(element, i);
                    } else {
                        subset[i].looseAdd(element);
                        fixExcess(i);
                    }
                }
            }
        }
    
        /**
         * 将element插入到locale位置.其后的元素往后移
         * 
         * @param element
         * @param locale
         */
        private void insertEle(int element, int locale) 
        {
            for (int i = dataCount; i > locale; i--) {
                data[i] = data[i - 1];
            }
            data[locale] = element;
            dataCount++;
            // System.out.println(dataCount+"  "+childCount);
        }
    
        /**
         * 将subset[i]拆分为两个元素个数为MINIMUM,子树数目为MINIMUM+1的两个节点. 分别存放在set1,和set2
         * 
         * @param set1
         * @param set2
         * @param i
         */
        private void divoteSub(IntBalancedSet set1, IntBalancedSet set2, int i) 
        {
            System.arraycopy(subset[i].data, 0, set1.data, 0, MINIMUM);
            System.arraycopy(subset[i].subset, 0, set1.subset, 0, MINIMUM + 1);
            System.arraycopy(subset[i].data, MINIMUM + 1, set2.data, 0, MINIMUM);
            System.arraycopy(subset[i].subset, MINIMUM + 1, set2.subset, 0, MINIMUM + 1);
            set1.dataCount = MINIMUM;
            set1.childCount = subset[i].childCount / 2;
            set2.dataCount = MINIMUM;
            set2.childCount = subset[i].childCount / 2;
        }
    
        /**
         * 调用此方法必须保证除了subset[i]有MAXIMUM+1个元素外,整棵B-树仍然有效的
         * 将subset[i]拆分为两个元素个数为MINIMUM的节点.在将节点插入到根节点的i和i+1位置
         * 
         * @param i
         */
        private void fixExcess(int i) 
        {
            if (subset[i].dataCount > MAXIMUM) {
                IntBalancedSet set1 = new IntBalancedSet();
                IntBalancedSet set2 = new IntBalancedSet();
                insertEle(subset[i].data[MINIMUM], i);// 在父节点插入该中间元素.
                divoteSub(set1, set2, i);
                subset[i] = set1;
                for (int j = childCount; j > i + 1; j--) {
                    subset[j] = subset[j - 1];
                }
                subset[i + 1] = set2;
                childCount++;
                // System.out.println(data[0]);
            }
        }
    
        /**
         * 返回一个新的引用中的data和subset指向当前节点的data和subset;
         * 
         * @return
         */
        private IntBalancedSet copyData() 
        {
            IntBalancedSet copy;
            copy = new IntBalancedSet();
            copy.data = data;
            copy.dataCount = dataCount;
            copy.childCount = childCount;
            copy.subset = subset;
            return copy;
        }
    
        @Override
        public Object clone() 
        {
            IntBalancedSet copy;
            copy = new IntBalancedSet();
            copy.data = data.clone();
            copy.dataCount = dataCount;
            copy.childCount = childCount;
            copy.subset = subset.clone();
            return copy;
        }
    
        /**
         * 在B-树中查找target.
         * 
         * @param target
         * @return
         */
        public boolean contains(int target) 
        {
            int i = firstGE(target);
            // System.out.println("i:"+i);
            if (i == dataCount) {
                if (childCount == 0)
                    return false;
                else
                    return subset[i].contains(target);
            } 
            else {
                if (target == data[i]) {
                    return true;
                } 
                else {
                    if (childCount == 0)
                        return false;
                    else
                        return subset[i].contains(target);
                }
            }
        }
    
        /**
         * 返回根节点中第一个大于或等于target的元素的位置 如果没有这样的元素,则返回dataCount
         * 
         * @param target
         * @return
         */
        private int firstGE(int target) 
        {
            int i = 0;
            for (; i < dataCount; i++) {
                if (data[i] >= target)
                    return i;
            }
            return i;
        }
    
        /**
         * 在集合中删除元素
         * 
         * @param target
         * @return
         */
        public boolean remove(int target) 
        {
            boolean answer = looseRemove(target);
            /**
             * 如果根节点没有元素,并且仅有一个子节点.那么删除子节点
             */
            if ((dataCount == 0) && (childCount == 1)) {
                dataCount = subset[0].dataCount;
                childCount = subset[0].childCount;
                data = subset[0].data;
                subset = subset[0].subset;
            }
            return answer;
        }
    
        /**
         * 如果target在集合中,将他删除并返回true.否则返回false 执行该方法后根节点的元素数目可能比MINIMUM小1
         * 
         * @param target
         * @return
         */
        private boolean looseRemove(int target) 
        {
            int i = firstGE(target);
            if (childCount == 0) {
                if (i != dataCount && data[i] == target) {
                    // 在data[i]中找到元素.并且没有子节点
                    cover(i);
                    return true;
                } else {
                    return false;
                }
            } else {
                if (i != dataCount && data[i] == target) {
                    /**
                     * 在data[i]中找到元素.但有子节点.将子节点中的最大元素覆盖i.既在所有比 data[i]小的元素集合中的最大值.
                     * subset[i]的元素数目能比最小值小1
                     */
    
                    data[i] = subset[i].removeBiggest();
                    if (subset[i].dataCount < MINIMUM)
                        fixShortage(i);
                    return true;
                } else {
                    /**
                     * 在data[i]中找不到元素.但有子节点.递归调用子节点的该方法.
                     */
                    boolean answer = subset[i].looseRemove(target);
                    if (subset[i].dataCount < MINIMUM)
                        fixShortage(i);
                    return answer;
                }
            }
        }
    
        /**
         * 当subset[i]只有MINIMUM-1个元素时调用此方法 该方法使根节点的元素个数比MINIMU小1
         * 
         * @param i
         */
        private void fixShortage(int i) 
        {
            if (i != 0 && subset[i - 1].dataCount > MINIMUM) {
                /**
                 * 如果subset[i-1]的元素数目比MINIMUM大.那么将data[i-1]的值插入到subset[i]
                 * 的data[0]位置.再将subset[i-1]的最后个元素转移到data[i-1]的位置.如果subset[i-1]
                 * 有子树那么将subset[i-1]的最大子树添加到subset[i]的subset[0]位置.
                 */
                subset[i].insertEle(data[i - 1], 0);
                data[i - 1] = subset[i - 1].cover(subset[i - 1].dataCount - 1);
                if (subset[i - 1].childCount != 0) {
                    subset[i].addSubset(subset[i - 1].coverSub(subset[i - 1].childCount - 1), 0);
                }
                return;
            }
            if (i != 0 && subset[i - 1].dataCount == MINIMUM) {
                subset[i - 1].insertEle(data[i - 1], subset[i - 1].dataCount);
                cover(i - 1);
                combineSub(subset[i - 1], subset[i]);
                coverSub(i);
                return;
            }
            
            if (i < dataCount && subset[i + 1].dataCount > MINIMUM) {
                subset[i].insertEle(data[i], subset[i].dataCount);
                data[i] = subset[i + 1].cover(0);
                if (subset[i + 1].childCount != 0) {
                    subset[i].addSubset(subset[i + 1].coverSub(0),
                            subset[i].childCount);
                }
                return;
            }
            
            if (i < dataCount && subset[i + 1].dataCount == MINIMUM) {
                subset[i + 1].insertEle(data[i], 0);
                cover(i);
                combineSub(subset[i], subset[i + 1]);
                coverSub(i + 1);
                return;
            }
        }
    
        private int removeBiggest() 
        {
            if (childCount == 0) {
    
                return data[--dataCount];
            } else {
                int answer = subset[childCount - 1].removeBiggest();
                if (subset[childCount - 1].dataCount < MINIMUM) {
                    fixShortage(childCount - 1);
                }
                return answer;
            }
        }
    
        /**
         * 将set2的元素和孩子节点添加到set1的后面;保证set1+set2的元素和不大于MAXIMUM
         * 
         * @param set1
         * @param set2
         */
        private void combineSub(IntBalancedSet set1, IntBalancedSet set2) {
    
            for (int i = 0; i < set2.dataCount; i++) {
                // System.out.println(" combineSub "+set1.dataCount+"  "+set2.dataCount);
                set1.data[set1.dataCount++] = set2.data[i];
            }
            for (int i = 0; i < set2.childCount; i++) {
                set1.subset[set1.childCount++] = set2.subset[i];
            }
        }
    
        /**
         * 删除节点中i位置的子节点.其后的子节点往前移动一个位置.
         * 
         * @param i
         */
        private IntBalancedSet coverSub(int i) 
        {
            IntBalancedSet answer = subset[i];
            for (int j = i; j < childCount; j++) {
                subset[j] = subset[j + 1];
            }
            childCount--;
            return answer;
        }
    
        /**
         * 删除节点中i位置的元素.其后的元素往前移动一个位置.
         * 
         * @param i
         */
        private int cover(int i) {
            int answer = data[i];
            for (int j = i; j < dataCount; j++) {
                data[j] = data[j + 1];
            }
            dataCount--;
            return answer;
        }
    
        // private void tranferEle(int i,int flag){
        // int dl=i+(flag==-1?0:flag);//datalocation
        // subset[i].insertEle(data[dl], 0);
        // data[dl]=subset[i+flag].data];
        // if(subset[i-1].childCount!=0){
        // subset[i-1].addSubset(subset[subset[i-1].childCount--],0);
        // }
        // }
        /**
         * 调用该方法的节点必须保证其子节点的数目比B-树要求的少一 调用后将sub添加到l位置.原本l后的节点往后移一个位置
         * 
         * @param sub
         * @param l
         */
        private void addSubset(IntBalancedSet sub, int l) 
        {
            for (int i = childCount; i > l; i--) {
                subset[i] = subset[i - 1];
            }
            subset[l] = sub;
            childCount++;
        }
    
        // private int removeLastest(){
        //
        // }
        public void print(int indent) 
        {
            final int EXTRA_INDENTATION = 4;
            int i;
            int space;
            for (space = 0; space < indent; space++) {
                System.out.print(" ");
            }
            for (i = 0; i < dataCount; i++) {
                System.out.print(data[i] + ",");
            }
            System.out.print("DC:" + dataCount + "  CC:" + childCount);
            System.out.println();
            for (i = childCount - 1; i >= 0; i--) {
                subset[i].print(indent + EXTRA_INDENTATION);
            }
        }
    
        public static void main(String[] args) 
        {
            IntBalancedSet set = new IntBalancedSet();
            Random rg = new Random();
            
            for (int i = 0; i < 2000; i++) {
                int num = rg.nextInt(10000);
                System.out.println("Adding " + num);
                set.add(num);
                // System.out.println("tree so far:");
                // set.print(4);
            }
            
            System.out.println("final version of tree");
            set.print(4);
            
            int num = rg.nextInt(10000);
            if (set.contains(num))
                System.out.println("found it!");
            else
                System.out.println("all that time, and nothing to show for it!");
        }
    }
  • 相关阅读:
    【35】单层卷积网络(simple convolution)
    【34】三维卷积
    【33】卷积步长讲解(Strided convolutions)
    【32】Padding(填充)原理讲解
    【31】更多的边缘检测方法
    08-----pymysql模块使用
    07-----多表查询
    06-----单表查询
    05-----数据的增删改
    04-----外键的变种 三种关系
  • 原文地址:https://www.cnblogs.com/rilley/p/2810140.html
Copyright © 2011-2022 走看看