All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.data2viz.voronoi.RedBlackTree.kt Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2018-2019. data2viz sàrl.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

package io.data2viz.voronoi

import io.data2viz.voronoi.RedBlackColor.*

class RedBlackTree {

    var root: RedBlackNode? = null

    fun insert(node: RedBlackNode, afterNode: RedBlackNode? = null): RedBlackNode {

        var parent: RedBlackNode?
        var grandpa: RedBlackNode?
        var uncle: RedBlackNode?

        var after = afterNode

        if (after != null) {
            node.P = after
            node.N = after.N
            after.N?.P = node
            after.N = node
            if (after.R != null) {
                after = after.R
                while (after!!.L != null) after = after.L!!
                after.L = node
            } else {
                after.R = node
            }
            parent = after
        } else if (root != null) {
            after = root!!.first()
            node.P = null
            node.N = after
            after.P = node
            after.L = node
            parent = after
        } else { //first insertion, set the root
            node.P = null
            node.N = null
            root = node
            parent = null
        }
        node.L = null
        node.R = null
        node.U = parent

        after = node

        while (parent?.C == RED) {
            grandpa = parent.U
            if (parent === grandpa!!.L) {
                uncle = grandpa!!.R
                if (uncle?.C == RED) {
                    parent.C = BLACK
                    uncle.C = BLACK
                    grandpa.C = RED
                    after = grandpa
                } else {
                    if (after === parent.R) {
                        rotateLeft(parent)
                        after = parent
                        parent = after.U
                    }
                    parent!!.C = BLACK
                    grandpa.C = RED
                    rotateRight(grandpa)
                }
            } else {
                uncle = grandpa!!.L
                if (uncle?.C == RED) {
                    parent.C = BLACK
                    uncle.C = BLACK
                    grandpa.C = RED
                    after = grandpa
                } else {
                    if (after === parent.L){
                        rotateRight(parent)
                        after = parent
                        parent = after.U!!
                    }
                    parent.C = BLACK
                    grandpa.C = RED
                    rotateLeft(grandpa)
                }
            }
            parent = after!!.U
        }
        root!!.C = BLACK
        return node
    }

    fun remove(toRemove: RedBlackNode){
        var node: RedBlackNode? = toRemove
        node!!.N?.P = node.P
        node.P?.N = node.N

        node.N = null
        node.P = null

        var parent = node.U
        var sibling: RedBlackNode?
        val left = node.L
        val right = node.R
        val next: RedBlackNode?
        val red: RedBlackColor

        if (left == null) { next = right }
        else if (right == null) { next = left }
        else { next = right.first() }

        if(parent != null){
            if (parent.L === node) { parent.L = next }
            else { parent.R = next }
        } else { root = next }

        if (left != null && right != null ){
            red = next!!.C
            next.C = node.C
            next.L = left
            left.U = next
            if (next !== right) {
                parent = next.U
                next.U = node.U
                node = next.R
                parent!!.L = node
                next.R = right
                right.U = next
            } else {
                next.U = parent
                parent = next
                node = next.R
            }
        } else {
            red = node.C
            node = next
        }

        if (node != null) {node.U = parent}
        if (red == RED) return
        if (node!=null && node.C == RED) {
            node.C = BLACK
            return
        }

        do {
            if (node === root) break
            if (node === parent!!.L){ //node is not root => parent not null
                sibling = parent!!.R
                if (sibling?.C == RED){
                    sibling.C = BLACK
                    parent.C = RED
                    rotateLeft(parent)
                    sibling = parent.R
                }
                if (sibling?.L?.C == RED || sibling?.R?.C == RED) {
                    if (sibling.R == null || sibling.R?.C == BLACK) {
                        sibling.L!!.C = BLACK
                        sibling.C = RED
                        rotateRight(sibling)
                        sibling = parent.R
                    }

                    sibling!!.C = parent.C
                    parent.C = BLACK
                    sibling.R!!.C = BLACK
                    rotateLeft(parent)
                    node = root
                    break
                }
            } else {
                sibling = parent!!.L
                if (sibling?.C == RED){
                    sibling.C = BLACK
                    parent.C = RED
                    rotateRight(parent)
                    sibling = parent.L
                }
                if( sibling?.L?.C == RED || sibling?.R?.C == RED) {
                    if (sibling.L == null || sibling.L?.C == BLACK) {
                        sibling.R?.C = BLACK
                        sibling.C = RED
                        rotateLeft(sibling)
                        sibling = parent.L
                    }
                    sibling?.C = parent.C
                    parent.C = BLACK
                    parent.L?.C = BLACK
                    rotateRight(parent)
                    node = root
                    break
                }
            }

            sibling?.C = RED
            node = parent
            parent = parent.U

        } while ( node?.C == BLACK)

        if (node != null) {node.C = BLACK
        }
    }

    fun rotateLeft(node: RedBlackNode) {
        val p = node
        val q = node.R
        val parent = p.U

        if (parent != null) {
            if (parent.L === p) {
                parent.L = q
            } else {
                parent.R = q
            }
        } else {
            root = q
        }
        q!!.U = parent
        p.U = q
        p.R = q.L
        if (p.R != null) {
            p.R!!.U = p
        }
        q.L = p
    }

    fun rotateRight(node: RedBlackNode) {
        val p = node           //le
        val q = node.L         //le nœud qui remplace la cible
        val parent = p.U       //le parent de la cible

        if (parent != null) {
            if (parent.L === p) {
                parent.L = q
            } else {
                parent.R = q
            }
        } else {
            root = q  //pas de parent, la cible était le root. Root change pour devenir q
        }
        q!!.U = parent
        p.U = q
        p.L = q.R
        if(p.L != null) {p.L!!.U = p}
        q.R = p
    }
}

fun  RedBlackNode.first(): RedBlackNode {
    var node = this
    while (node.L != null) node = node.L!!
    return node
}

enum class RedBlackColor {
    RED, BLACK
}


class RedBlackNode(val node: T) {
    var U: RedBlackNode? = null //parent
    var L: RedBlackNode? = null //left
    var R: RedBlackNode? = null //right
    var P: RedBlackNode? = null //previous
    var N: RedBlackNode? = null //next
    var C: RedBlackColor = RED     //color - true for red, false for black

    fun clean() {
        U = null
        L = null
        R = null
        P = null
        N = null
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy