view src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/transaction/node/redBlackTree/BlackTreeNode.java @ 329:2a0cb1f0ba4e

rename Error package
author kono
date Sat, 08 Jul 2017 21:05:55 +0900
parents 1f929fe9c153
children
line wrap: on
line source

package jp.ac.u_ryukyu.ie.cr.jungle.transaction.node.redBlackTree;

import jp.ac.u_ryukyu.ie.cr.jungle.data.treemap.Rotate;
import jp.ac.u_ryukyu.ie.cr.jungle.data.treemap.TreeMap;
import jp.ac.u_ryukyu.ie.cr.jungle.transaction.node.TreeNode;
import jp.ac.u_ryukyu.ie.cr.jungle.util.DefaultEither;
import jp.ac.u_ryukyu.ie.cr.jungle.util.Either;
import jp.ac.u_ryukyu.ie.cr.jungle.util.jungleError.Error;
import org.junit.Test;

import java.nio.ByteBuffer;

import static jp.ac.u_ryukyu.ie.cr.jungle.util.jungleError.TreeNodeError.NOT_USE_METHOD;

public class BlackTreeNode extends ColorlessTreeNode {

    public BlackTreeNode(ColorlessTreeNode node) {
        this(node.getAttrs(), node.key(), node.value(), node.left(), node.right());
    }

    public BlackTreeNode(TreeMap<String, ByteBuffer> _attrs, String balanceKey, ByteBuffer value, ColorlessTreeNode left, ColorlessTreeNode right) {
        super(_attrs, balanceKey, value, left, right);
    }

    @Override
    public ColorlessTreeNode createNode(TreeMap<String, ByteBuffer> newAttrs, String insertKey, ByteBuffer insertValue, ColorlessTreeNode left, ColorlessTreeNode right) {
        return new BlackTreeNode(newAttrs, insertKey, insertValue, left, right);
    }

    @Override
    public TreeNode createNewNode() {
        return null;//new BlackTreeNode();
    }

    @Override
    protected RebuildNode deleteNode() {
        ColorlessTreeNode emptyNode = new EmptyTreeNode(value());
        return new RebuildNode(true, emptyNode);
    }

    public TreeNode clone() {
        return new BlackTreeNode(getAttrs(), key(), value(), left(), right());
    }

    @Override
    public Either<Error, TreeNode> appendRootNode() {
        return DefaultEither.newA(NOT_USE_METHOD);
    }

    @Override
    public int compareTo(TreeNode o) {
        return this.getHash() - o.getHash();
    }

    @Override
    public int getHash() {
        return value().hashCode();
    }

    @Override
    public boolean isRed() {
        return false;
    }

    @Override
    public boolean empty() {
        return false;
    }

    @Override
    public Rotate checkRotate(Rotate side) {
        return Rotate.N;
    }

    @Override
    protected ColorlessTreeNode insBalance() {
        Rotate spin = left().checkRotate(Rotate.L);
        if (spin == Rotate.R) {
            ColorlessTreeNode newLeftChild = new BlackTreeNode(left().left().getAttrs(), left().left().key(), left().left().value(), left().left().left(), left().left().right());
            ColorlessTreeNode newRightChild = new BlackTreeNode(getAttrs(), key(), value(), left().right(), right());
            return new RedTreeNode(left().getAttrs(), left().key(), left().value(), newLeftChild, newRightChild);
        } else if (spin == Rotate.LR) {
            ColorlessTreeNode newLeftChild = new BlackTreeNode(left().getAttrs(), left().key(), left().value(), left().left(), left().right().left());
            ColorlessTreeNode newRightChild = new BlackTreeNode(getAttrs(), key(), value(), left().right().right(), right());
            return new RedTreeNode(left().right().getAttrs(), left().right().key(), left().right().value(), newLeftChild, newRightChild);
        }

        spin = right().checkRotate(Rotate.R);
        if (spin == Rotate.L) {
            ColorlessTreeNode newLeftChild = new BlackTreeNode(getAttrs(), key(), value(), left(), right().left());
            ColorlessTreeNode newRightChild = new BlackTreeNode(right().right().getAttrs(), right().right().key(), right().right().value(), right().right().left(), right().right().right());
            return new RedTreeNode(right().getAttrs(), right().key(), right().value(), newLeftChild, newRightChild);
        } else if (spin == Rotate.RL) {
            ColorlessTreeNode newLeftChild = new BlackTreeNode(getAttrs(), key(), value(), left(), right().left().left());
            ColorlessTreeNode newRightChild = new BlackTreeNode(right().getAttrs(), right().key(), right().value(), right().left().right(), right().right());
            return new RedTreeNode(right().left().getAttrs(), right().left().key(), right().left().value(), newLeftChild, newRightChild);
        }
        return this;
    }

    @Override
    @Test
    public int checkDepth(int count, int minCount) { // test method
        count++;
        minCount = left().checkDepth(count, minCount);
        minCount = right().checkDepth(count, minCount);
        return minCount;
    }

    @Override
    protected RebuildNode replaceNode(ColorlessTreeNode parent) {
        ColorlessTreeNode newNode;
        if (this.left().empty() && this.right().empty()) { //自身を削除する
            return deleteNode();//黒が1つ減るので木のバランスを取る
        } else if (!this.left().empty() && this.right().empty()) { //左の部分木を昇格させる
            newNode = createNode(left().getAttrs(), left().key(), left().value(), left().left(), left().right());
            if (!this.left().isRed()) //昇格させる木のrootが黒だったらバランスを取る
                return new RebuildNode(true, newNode);
            return new RebuildNode(false, newNode);
        } else if (this.left().empty() && !this.right().empty()) { //右の部分木を昇格させる
            newNode = createNode(right().getAttrs(), right().key(), right().value(), right().left(), right().right());
            if (!this.right().isRed()) //昇格させる木のrootが黒だったらバランスを取る
                return new RebuildNode(true, newNode);
            return new RebuildNode(false, newNode);
        } else {//子ノードが左右にある場合 二回目はここには入らない
            //左の部分木の最大の値を持つNodeと自身を置き換える
            ColorlessTreeNode cur = this.left();
            while (!cur.right().empty()) { //左の部分期の最大値を持つNodeを取得する
                cur = cur.right();
            }
            if (!this.left().right().empty()) { //左の部分木が右の子を持っているか
                RebuildNode leftSubTreeNodeRebuildNode = this.left().deleteSubTreeMaxNode(null, Rotate.L);//最大値を削除した左の部分木を返す。rootはthisと同じ。
                if (leftSubTreeNodeRebuildNode.rebuild()) {
                    ColorlessTreeNode leftSubTreeNode = leftSubTreeNodeRebuildNode.getNode();
                    ColorlessTreeNode newParent = createNode(cur.getAttrs(), cur.key(), cur.value(), leftSubTreeNode, this.right());
                    return leftSubTreeNode.deleteBalance(newParent);
                }
                ColorlessTreeNode leftSubTreeNode = leftSubTreeNodeRebuildNode.getNode();
                newNode = createNode(cur.getAttrs(), cur.key(), cur.value(), leftSubTreeNode, this.right()); //rootをcurと入れ替えることでNodeの削除は完了する
                return new RebuildNode(false, newNode);
            } else {
                RebuildNode leftSubTreeNodeRebuildNode = this.left().replaceNode(this);//右の子がいなかった場合、左の子を昇格させるだけで良い。
                if (leftSubTreeNodeRebuildNode.rebuild()) {
                    ColorlessTreeNode node = leftSubTreeNodeRebuildNode.getNode();
                    ColorlessTreeNode newParent = createNode(this.left().getAttrs(), this.left().key(), this.left().value(), node, this.right());
                    return node.deleteBalance(newParent);
                }
                ColorlessTreeNode leftSubTreeNode = leftSubTreeNodeRebuildNode.getNode();
                newNode = createNode(this.left().getAttrs(), this.left().key(), this.left().value(), leftSubTreeNode, this.right());
                return new RebuildNode(false, newNode);
            }
        }
    }
}