Groovy实现BTree的构建,插入,删除,查询以及遍历

Groovy实现BTree的构建,插入,删除,查询以及遍历

package com.cqs

import org.springframework.util.Assert

import java.util.concurrent.ConcurrentLinkedQueue

/**
 * Created by cqs on 2017/11/25.
 */
class BTree {

    private Node root //根节点
    private int high //高度
    private int degree = 6//树阶
    private int elements = 0 //总关键数

    BTree() {
        root = new Node(true, null)
        high = 0
        assert degree > 2
    }


    private def class Node {
        int n = 0 //节点包含关键数数量
        K[] keys = new K[degree - 1] //关键字数组
        def children = new Node[degree] //孩子数组
        Node parent = null//父节点
        boolean leaf //是否为叶子节点

        Node(boolean leaf, Node parent) {
            this.parent = parent
            this.leaf = leaf
        }
        //是否节点已经满了
        def full() {
            return n == maxKeys()
        }

//        def min() {
//            return n == minKeys()
//        }

        K previous2(int pos) {
            if (this.leaf) return null
            Assert.isTrue(pos >= 0 && pos < this.n, "${pos} 必须为非负数且小于关键数个数")
            Node node = this.children[pos]
            while (!node.isLeaf()) {
                node = node.children[node.n]
            }
            return node.keys[node.n - 1]
        }

        K previous(K key) {
            return previous2(this.indexKey(key))
        }

        //获取后继节点(右子树离key最近的节点)
        K successor(K key) {
            int pos = this.indexKey(key)
            Node node = this.children[pos + 1]
            while (!node.isLeaf()) {
                node = node.children[0]
            }
            return node.keys[0]
        }

        //非根节点中关键字数量下限
        def minKeys() {
            return (int) (Math.ceil(degree / 2)) - 1
        }
        //非根节点中关键字数量上限
        def maxKeys() {
            return degree - 1
        }

        //节点的关键字数量是否合理
        def keyNumLegal() {
            boolean result
            if (this == root) {
                result = this.n <= maxKeys() && (root.isLeaf() || root.n > 0)
            } else {
                result = this.n >= minKeys() && this.n <= maxKeys()
            }
            if (!result) {
                println "error ${this.n} ${this.minKeys()} ${this.maxKeys()} -- ${getActKeys()}"
                assert result
            }
            return result
        }

        /**
         *  返回非负数:包含key 且结果为key在数组keys的索引
         *  返回负数,假定返回结果为index 说明节点中不包含key
         *  若this是叶子节点 那么-index-1就是要插入的位置
         *  若this是非叶子节点 那么 -index-1 就是孩子节点的索引
         *  -index-1
         * @param key
         * @return
         */
        int indexKey(K key) {
            assert getActKeys() != null
            return Arrays.binarySearch(getActKeys(), key)
        }

        //关键字数组
        K[] getActKeys() {
            return this.keys[0..<(this.n)]
        }

        //孩子数组
        Node[] getActChildren() {
            if (isLeaf()) return []
            return this.children[0..this.n]
        }

        //更新关键字
        def update(int idx, K key) {
            if (idx >= this.n)
                throw new ArrayIndexOutOfBoundsException("${idx}值太大 超出${this.n - 1}")
            //println "UPDATE ${idx} ${key} ${this.getActKeys()}"
            this.keys[idx] = key
        }

        //检查关键字是否合法
        def checkKeys() {
            for (int i = 0; i < getActKeys().length; i++) {
                assert getActKeys()[i] != null
            }
            assert keyNumLegal()
        }

        //检查子树是否合法
        def checkActChildren() {
            for (int i = 0; i < getActChildren().length; i++) {
                assert getActChildren()[i] != null
            }
        }

        //just delete key
        // 不涉及孩子节点
        def deleteKey(final int pos) {
            assert pos < this.n
            while (pos < this.n - 1) {
                this.keys[pos] = this.keys[pos + 1]
                ++pos
            }
            --this.n
        }

        //仅仅在指定位置写入关键字
        def insertKey(int pos, K key) {
            if (key == null) {
                throw new IllegalArgumentException("写入的关键字不能为空")
            }
            if (this.indexKey(key) >= 0) {
                throw new IllegalAccessError("${key}已经存在,无法再次插入")
            }
            int i = this.n - 1
            assert pos < degree - 1
            //this.checkKeys()
            while (i >= pos) {
                this.keys[i + 1] = this.keys[i]
                --i
            }
            this.keys[pos] = key
            ++this.n
            // this.checkKeys()
//        println "keys个数: ${node.n}  总元素:${this.elements} -----${root.getActKeys()}"
        }

        //向左移动孩子节点
        def lMovieChild(int pos) {
            while (pos < this.n) {
                this.children[pos] = this.children[pos + 1]
                ++pos
            }
        }

        //向右移动孩子节点
        def rMovieChild(int pos) {
            while (pos > 0) {
                this.children[pos] = this.children[pos - 1]
                --pos
            }
        }

        //this.keys[pos]下沉到左孩子节点 然后右孩子节点最小元素krn代替this.keys[pos] ,右孩子删除krn
        def rSiblingBorrow(int pos) {
            assert pos < this.n
            Node rn = this.children[pos + 1]
            Node cn = this.children[pos]
            K krn = rn.keys[0]
            K knode = this.keys[pos]
            if (rn.isLeaf()) {
                rn.deleteKey(0)
                cn.insertKey(cn.n, knode)
                this.update(pos, krn)
            } else {
                //
                Node rs = rn.children[0]
                //先移动孩子节点 后删除
                rn.lMovieChild(0)
                rn.deleteKey(0)


                cn.insertKey(cn.n, knode)
                cn.children[cn.n] = rs
                //更新父节点
                cn.children[cn.n].parent = cn
                this.update(pos, krn)
            }
        }

        //this.keys[pos]下沉到右孩子节点 然后左孩子节点最小元素kln代替this.keys[pos] ,左孩子删除kln
        //"向左兄弟节点借元素"
        def lSiblingBorrow(int pos) {
            assert pos > 0
            Node ln = this.children[pos - 1]
            Node cn = this.children[pos]
            K kln = ln.keys[ln.n - 1]
            //注意更新父节点索引为pos-1 这里要区别rSiblingBorrow
            int parentIndex = pos - 1
            K knode = this.keys[parentIndex]


            if (ln.isLeaf()) {
                ln.deleteKey(ln.n - 1)
                cn.insertKey(0, knode)
                this.update(parentIndex, kln)
            } else {
                //
                Node rs = ln.children[ln.n]
                //不用移动ln的孩子节点 删除之后ln元素减一
                ln.deleteKey(ln.n - 1)
                cn.insertKey(0, knode)
                //右移孩子节点
                cn.rMovieChild(cn.n)
                cn.children[0] = rs
                rs.parent = cn
                this.update(parentIndex, kln)
            }
        }

        //!!!!
        //关键字key + 左右孩子节点合并成新的节点
        def mergeSibling(final int pos, K key) {
            assert pos >= 0

            Node lc = this.children[pos]
            Node rc = this.children[pos + 1]

            assert lc.n == lc.minKeys()
            assert rc.n == rc.minKeys()
//            println("BEFORE++++++++++++++++++ ${getActKeys()}")
//            this.getActChildren().each { println "${it.getActKeys()}" }

            //孩子节点向前移动
            int p = pos + 1
            while (p < this.n) {
                this.children[p] = this.children[p + 1]
                ++p
            }

            //删除key
            this.deleteKey(pos)

            //key合并至lc
            lc.keys[lc.minKeys()] = key //将key置于lc节点中

            //rc合并至lc
            rc.minKeys().times {
                lc.keys[1 + lc.minKeys() + it] = rc.keys[it]
            }
            lc.n = maxKeys()
//            println("AFTER +++++++++++++++++++++++++ ${getActKeys()}----------${lc.getActKeys()}")
//            this.getActChildren().each { println "${it.getActKeys()}" }
            if (!lc.isLeaf()) {
                //合并孩子节点
                p = lc.minKeys() + 1
                (rc.minKeys() + 1).times {
                    lc.children[p] = rc.children[it]
                    //更新父节点
                    rc.children[it].parent = lc
                    ++p
                }
            }
            //
            if (root.n == 0) {
                root = lc
                --high
                root.parent = null
            }
        }
    }

    //向树种添加key元素 若树中存在那么更新 不存在的话就是新增
    def put(K key) {
//        println "--------------------INSERT ${key}--------------------"
        def idx = root.indexKey(key)
        if (idx >= 0) {
            root.update(idx, key)
            return
        }
        if (root.full()) {
            def oroot = root
//            print "------------------oldRoot: ${oroot.getActKeys()}--------------"
            root = new Node(false, null)
            this.high += 1
            root.children[0] = oroot
            oroot.parent = root
//            println "${oroot.parent.getActKeys()} ------!####################"
            splitChild(0, oroot)
//            println("###################----root: ${root.getActKeys()}################################")
        }
        insertNonFull(root, key)
    }

    //删除元素
    def delete(K key) {
        int ele = this.elements
        delete(root, key)
        assert ele == this.elements + 1
        println "删除${key}成功"
    }

    //从node为根的子树种删除元素key
    def delete(Node node,final K key) {
        node.keyNumLegal()
        int pos = node.indexKey(key)
        if (pos >= 0) {//1)
            if (node.isLeaf()) {
                node.deleteKey(pos)
                --elements
            } else {//2)
                Node lc = node.getActChildren()[pos]
                Node rc = node.getActChildren()[pos + 1]
                if (lc.n > lc.minKeys()) {//2a)
                    K previous = node.previous(key)
                    node.update(pos, previous)
                    delete(lc, previous)
                } else if (rc.n > rc.minKeys()) {//2b)
                    K successor = node.successor(key)
                    node.update(pos, successor)
                    delete(rc, successor)
                } else {//2c)
                    //move key from node to new node
//                    node.getActChildren().each { println "${it.getActKeys()}" }
//                    println("${node.getActChildren()},${lc.getActKeys()},${rc.getActKeys()}")
//                    node.getActChildren().each { println " child:${it.getActKeys()}" }
                    node.mergeSibling(pos, key)
                    delete(lc, key)
                }
            }
        } else {//3) not exist in node
            pos = -pos - 1
            if (node.isLeaf()) {
//                bdf()
//                def i = node.indexKey(key)
//                println " ${node.indexKey(key)} --------${pos}! -- ${node.getActKeys()}!!!${key} 不存在,删除失败 ${root.getActKeys()}"
                throw new IllegalArgumentException("${pos}! -- ${node.getActKeys()}!!!${key} 不存在,删除失败")
            } else {
                //找到区间(孩子节点)
                Node c = node.children[pos]
                if (c.n == c.minKeys()) { //3a)
                    Node lsibling = pos > 0 ? node.children[pos - 1] : null
                    Node rsibling = pos < node.n ? node.children[pos + 1] : null

                    def borrow = {
                        if (lsibling != null) {//先判断是否能从左兄弟节点接
                            if (lsibling.n > lsibling.minKeys()) {//
                                node.lSiblingBorrow(pos)
                                return true
                            }
                        }
                        if (rsibling != null) {//左兄弟借失败的话再判断是否能从做兄弟节点接
                            if (rsibling.n > rsibling.minKeys()) {
                                node.rSiblingBorrow(pos)
                                return true
                            }
                        }
                        return false
                    }

                    //返回true 3a)否则进入3b)
                    boolean bw = borrow.call()

                    //检查兄弟节点均包含minKeys()个元素
                    def checkSiblingMin = {
                        if (lsibling != null && lsibling.n != lsibling.minKeys()) {
                            return false
                        }
                        if (rsibling != null && rsibling.n != rsibling.minKeys()) {
                            return false
                        }
                        return true
                    }
                    def ok = checkSiblingMin.call()
                    if (!bw && ok) {//3b)不能借到元素
                        if (lsibling != null) {
                            int n_pos = pos - 1 //这里要十分注意
                            node.mergeSibling(n_pos, node.keys[n_pos])
//                            println c == node.children[n_pos]
                            //左右孩子合并 原来c节点合并至c的左兄弟节点中 所以要更新"递归删除子树的根节点"
                            c = node.children[n_pos]
                        } else if (rsibling != null) {
                            node.mergeSibling(pos, node.keys[pos])
                        }
                    }
                }
                //递归删除
                delete(c, key)
            }
        }
    }

    //树中是否包含key 包含返回true 不包含返回false
    def contains(K key) {
        return containsNode(key) != null
    }

    //树中是否包含key 元素所在节点 不包含返回null
    def containsNode(K key) {
        int pos
        Node node = root
        while ((pos = node.indexKey(key)) < 0 && !node.isLeaf()) {
            node = node.children[-pos - 1]
        }
        return pos >= 0 ? node : null
    }

    //node没有满的情况下写入key
    private def insertNonFull(Node node, K key) {
        def pos = node.indexKey(key)
        if (pos >= 0) {
            node.update(pos, key)
            return
        }
        pos = -pos - 1
        assert pos < (this.degree - 1)
        assert pos <= node.n
        if (node.isLeaf()) {
            ++this.elements
            node.insertKey(pos, key)
            return
        } else {
            Node child = node.children[pos]

            assert child.parent != null

//            if (child.parent != node) {
//                println root
//                println root.getActChildren().each { println it.getActKeys() }
//                println "${node.getActKeys()}   -- ${node.isLeaf()}  -- ${key}"
//                println "${root.children[0].getActKeys()}   -- ${node.isLeaf()}  -- ${key}"
//                node.getActChildren().each { println it.parent.getActKeys() }
//                node.getActChildren().each { println it.getActKeys() }
//                println "------------------------------------"
//            }

            assert child.parent == node
            if (child == null) {
                assert child != null
            }
//            println "child: ${child.getActKeys()}"
            if (child.full()) {
                splitChild(pos, child)
                assert node.keys[pos] != null
                if (key.compareTo(node.keys[pos]) > 0) {
                    child = node.children[++pos]
                }
            }
            insertNonFull(child, key)
        }
    }

    /**
     *
     * @param index 分裂出来的元素组成的新结点 插入的node父节点keys的索引
     * @param node 待分裂的节点
     * @return
     */
    private def splitChild(int index, Node node) {
        assert node.n == this.degree - 1
        def parent = node.parent
        //parent.checkActChildren()
//        println "parent: ${parent.getActKeys()} ---  ${index}"
        Node rn = new Node(node.leaf, parent)

        int mid = node.minKeys()
//        println "${node.keys} ---- mid ${node.keys[mid]}"
        int p = node.n - 1
        rn.n = node.n - 1 - mid
        while (p > mid) {
            rn.keys[p - mid - 1] = node.keys[p]
            --p
        }

        if (!node.isLeaf()) {
            p = node.n - 1
            while (p >= mid) {
                rn.children[p - mid] = node.children[p + 1]
                //更新父节点
                rn.children[p - mid].parent = rn
                --p
            }
        }

        node.n = mid
//        this.elements -= 1
        parent.insertKey(index, node.keys[mid])
        p = parent.n - 1
        assert p < parent.maxKeys()
        while (p > index) {
            parent.children[p + 1] = parent.children[p]
            --p
        }
        parent.children[index + 1] = rn
        //上浮
        parent.keys[index] = node.keys[mid]
        //parent.checkActChildren()
        assert rn.parent == parent
        assert rn.parent == node.parent
        //rn.checkActChildren()
//        println "node ${node.getActKeys()} ------r ${rn.getActKeys()} ------------p ${parent.getActKeys()}"
    }

    //广度优先遍历树
    def bdf() {
        Queue q = new ConcurrentLinkedQueue<>()
        q.add(root)
        while (q.size() != 0) {
            Node nd = q.poll()
            q.addAll(nd.getActChildren())
            int level = level(nd)
            (level).times { print("---|") }
            println "${nd.getActKeys()} ---- ${level} ---${this.high}"
        }
    }

    //节点node在树中的那一层
    int level(Node node) {
        int th = 0
        if (node == null) throw new NullPointerException("节点不能为null")
        Node tmp = node
        while (tmp.parent != null) {
            tmp = tmp.parent
            th++
        }
        assert tmp == root
        return th
    }


    static void main(String[] args) {

        1.times {
            Set set = new HashSet<>()
//             set = new TreeSet<>()

             int size = 10 + 90 * (1 + it * it)

            def r = new Random()
            BTree bt = new BTree<>()

            size.times {
                int ele = r.nextInt(Math.abs(size * 100 * (it + 1)))
                set.add(ele)
                bt.put(ele)
            }

            50.times { print "#" }
            print "\t${it + 1}\t  -- ${bt.elements}"
            50.times { print "#" }
            println ""
            bt.bdf()

//            set = set.descendingSet()
            set.each {
//                100.times { print("-") }
//                println " DELETE ${it} "
                bt.delete(it)
//                bt.bdf()
            }

           assert bt.elements == 0

        }
    }

}

运行结果:


Groovy实现BTree的构建,插入,删除,查询以及遍历_第1张图片
2017-11-28_001923.png

你可能感兴趣的:(Groovy实现BTree的构建,插入,删除,查询以及遍历)