changeset 217:3b31dd5e5a28 OptionalTreeMap

delete use Taple fix
author tatsuki
date Tue, 01 Sep 2015 16:09:08 +0900
parents 9a410eddbfa4
children 7e1a59c2ede6
files src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/data/treemap/BlackNode.java src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/data/treemap/EmptyNode.java src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/data/treemap/Node.java src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/data/treemap/RedNode.java src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/data/treemap/Taple.java src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/data/treemap/TreeMap.java
diffstat 6 files changed, 181 insertions(+), 143 deletions(-) [+]
line wrap: on
line diff
--- a/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/data/treemap/BlackNode.java	Tue Sep 01 05:04:38 2015 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/data/treemap/BlackNode.java	Tue Sep 01 16:09:08 2015 +0900
@@ -14,9 +14,9 @@
 
 
     @Override
-    public Node<K, V> deleteNode() throws RotateParent {
+    public Taple deleteNode() {
         EmptyNode<K, V> emptyNode = new EmptyNode<>(key);
-        throw new RotateParent(emptyNode);
+        return new Taple<>(true, emptyNode);
     }
 
     @Override
@@ -85,20 +85,20 @@
 
     @Override
     @SuppressWarnings("unchecked")
-    public Node<K, V> replaceNode(Node<K, V> parent, Comparator ctr) throws RotateParent {
+    public Taple replaceNode(Node<K, V> parent, Comparator ctr) {
         Node<K, V> newNode;
         if (!this.left().isNotEmpty() && !this.right().isNotEmpty()) { //自身を削除する
             return deleteNode();//黒が1つ減るので木のバランスを取る
         } else if (this.left().isNotEmpty() && !this.right().isNotEmpty()) { //左の部分木を昇格させる
             newNode = createNode(left().getKey(), left().getValue(), left().left(), left().right());
             if (!this.left().isRed()) //昇格させる木のrootが黒だったらバランスを取る
-                throw new RotateParent(newNode);
-            return newNode;
+                return new Taple(true, newNode);
+            return new Taple(false, newNode);
         } else if (!this.left().isNotEmpty() && this.right().isNotEmpty()) { //右の部分木を昇格させる
             newNode = createNode(right().getKey(), right().getValue(), right().left(), right().right());
             if (!this.right().isRed()) //昇格させる木のrootが黒だったらバランスを取る
-                throw new RotateParent(newNode);
-            return newNode;
+                return new Taple(true, newNode);
+            return new Taple(false, newNode);
         } else {//子ノードが左右にある場合 二回目はここには入らない
             //左の部分木の最大の値を持つNodeと自身を置き換える
             Node<K, V> cur = this.left();
@@ -106,24 +106,25 @@
                 cur = cur.right();
             }
             if (this.left().right().isNotEmpty()) { //左の部分木が右の子を持っているか
-                try {
-                    Node<K, V> leftSubTreeNode = this.left().deleteSubTreeMaxNode(null, ctr, Rotate.L);//最大値を削除した左の部分木を返す。rootはthisと同じ。
-                    return createNode(cur.getKey(), cur.getValue(), leftSubTreeNode, this.right()); //rootをcurと入れ替えることでNodeの削除は完了する
-                } catch (RotateParent e) {
-                    Node<K, V> leftSubTreeNode = e.getParent();
+                Taple<K, V> leftSubTreeNodeTaple = this.left().deleteSubTreeMaxNode(null, ctr, Rotate.L);//最大値を削除した左の部分木を返す。rootはthisと同じ。
+                if (leftSubTreeNodeTaple.rebuild()) {
+                    Node<K, V> leftSubTreeNode = leftSubTreeNodeTaple.getNode();
                     Node<K, V> newParent = createNode(cur.getKey(), cur.getValue(), leftSubTreeNode, this.right());
                     return leftSubTreeNode.deleteBalance(newParent, ctr);
                 }
+                Node<K, V> leftSubTreeNode = leftSubTreeNodeTaple.getNode();
+                newNode = createNode(cur.getKey(), cur.getValue(), leftSubTreeNode, this.right()); //rootをcurと入れ替えることでNodeの削除は完了する
+                return new Taple(false, newNode);
             } else {
-                Node<K, V> leftSubTreeNode;
-                try {
-                    leftSubTreeNode = this.left().replaceNode(this, ctr);//右の子がいなかった場合、左の子を昇格させるだけで良い。
-                    return createNode(this.left().getKey(), this.left().getValue(), leftSubTreeNode, this.right());
-                } catch (RotateParent e) {
-                    Node<K, V> node = e.getParent();
-                    Node<K, V> newParent = createNode(this.left().getKey(), this.left().getValue(), node, this.right());
-                    return node.deleteBalance(newParent, ctr);
-                }
+                    Taple<K, V> leftSubTreeNodeTaple = this.left().replaceNode(this, ctr);//右の子がいなかった場合、左の子を昇格させるだけで良い。
+                    if (leftSubTreeNodeTaple.rebuild()) {
+                        Node<K, V> node = leftSubTreeNodeTaple.getNode();
+                        Node<K, V> newParent = createNode(this.left().getKey(), this.left().getValue(), node, this.right());
+                        return node.deleteBalance(newParent, ctr);
+                    }
+                    Node<K,V> leftSubTreeNode = leftSubTreeNodeTaple.getNode();
+                    newNode = createNode(this.left().getKey(), this.left().getValue(), leftSubTreeNode, this.right());
+                    return new Taple(false, newNode);
             }
         }
     }
--- a/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/data/treemap/EmptyNode.java	Tue Sep 01 05:04:38 2015 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/data/treemap/EmptyNode.java	Tue Sep 01 16:09:08 2015 +0900
@@ -44,13 +44,13 @@
     }
 
     @Override
-    public Node<K, V> replaceNode(Node<K, V> parent, Comparator ctr) { // not use method
-        return this;
+    public Taple<K, V> replaceNode(Node<K, V> parent, Comparator ctr) { // not use method
+        return new Taple<>(false, this);
     }
 
     @Override
-    protected Node<K,V> deleteNode() { //not use method
-        return this;
+    protected Taple<K, V> deleteNode() { //not use method
+        return new Taple<>(false, this);
     }
 
     @Override
--- a/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/data/treemap/Node.java	Tue Sep 01 05:04:38 2015 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/data/treemap/Node.java	Tue Sep 01 16:09:08 2015 +0900
@@ -80,72 +80,60 @@
     }
 
     @SuppressWarnings("unchecked")
-    public Node<K, V> delete(K key, Node<K, V> parent, Comparator ctr, Rotate side) throws RotateParent {
+    public Taple delete(K key, Node<K, V> parent, Comparator ctr, Rotate side) {
         if (this.isNotEmpty()) {
+            Taple taple;
             int result = compare(key, ctr);
+            if (result > 0) {
+                taple = right.delete(key, this, ctr, Rotate.R);
+            } else if (result < 0) {
+                taple = left.delete(key, this, ctr, Rotate.L);
+            } else { //Equal
+                taple = replaceNode(parent, ctr);
+            }
+            if (parent == null)
+                return taple;
+            Node<K, V> node = taple.getNode();
+            if (taple.rebuild()) {
+                return node.deleteBalance(parent, ctr);
+            }
 
-            try {
-                Node<K, V> node = null;
-                if (result > 0) {
-                    node = right.delete(key, this, ctr, Rotate.R);
-                    if (node == null)
-                        return null;
-                    if (parent == null)
-                        return node;
-                } else if (result < 0) {
-                    node = left.delete(key, this, ctr, Rotate.L);
-                    if (node == null)
-                        return null;
-                    if (parent == null)
-                        return node;
-                } else if (result == 0) {
-                    node = replaceNode(parent, ctr);
-                    if (parent == null)// equals
-                        return node;
-                    if (side == Rotate.R)
-                        return parent.createNode(parent.getKey(), parent.getValue(), parent.left(), node);
-                    else
-                        return parent.createNode(parent.getKey(), parent.getValue(), node, parent.right());
-                }
-                if (side == Rotate.L)
-                    return parent.createNode(parent.getKey(), parent.getValue(), node, parent.right());
-                else
-                    return parent.createNode(parent.getKey(), parent.getValue(), parent.left(), node);
-            } catch (RotateParent e) {
-                Node<K, V> node = e.getParent();
-                if (parent != null)
-                    return node.deleteBalance(parent, ctr);
-                return node;
-            }
+            Node<K, V> newParent;
+            if (side == Rotate.L)
+                newParent = parent.createNode(parent.getKey(), parent.getValue(), node, parent.right());
+            else
+                newParent = parent.createNode(parent.getKey(), parent.getValue(), parent.left(), node);
+
+            return new Taple<>(false, newParent);
         }
-        return null; // no key
+        return null;
     }
 
     @SuppressWarnings("unchecked")
-    public Node<K, V> deleteSubTreeMaxNode(Node<K, V> parent, Comparator ctr, Rotate side) throws RotateParent {
+    public Taple deleteSubTreeMaxNode(Node<K, V> parent, Comparator ctr, Rotate side) {
+        Taple taple;
         Node<K, V> node;
-        try {
-            if (right().isNotEmpty()) {//最大値のノードが取得できるまで潜る
-                node = right().deleteSubTreeMaxNode(this, ctr, Rotate.R);
-            } else {
-                node = this.replaceNode(parent, ctr);
-            }
-        } catch (RotateParent e) {
-            node = e.getParent();
-            if (parent == null)
-                throw e;
+        if (right().isNotEmpty()) {//最大値のノードが取得できるまで潜る
+            taple = right().deleteSubTreeMaxNode(this, ctr, Rotate.R);
+        } else {
+            taple = this.replaceNode(parent, ctr);
+        }
+        if (parent == null)
+            return taple;
+
+        if (taple.rebuild()) {
+            node = taple.getNode();
             return node.deleteBalance(parent, ctr);
         }
-        if (parent == null)
-            return node;
         if (side == Rotate.R)
-            return parent.createNode(parent.getKey(), parent.getValue(), parent.left(), node);
+            node = parent.createNode(parent.getKey(), parent.getValue(), parent.left(), taple.getNode());
         else
-            return parent.createNode(parent.getKey(), parent.getValue(), node, parent.right());
-
+            node = parent.createNode(parent.getKey(), parent.getValue(), taple.getNode(), parent.right());
+        return new Taple<>(false, node);
     }
 
-    public Node<K, V> deleteBalance(Node<K, V> parent, Comparator ctr) throws RotateParent {
+    public Taple<K, V> deleteBalance(Node<K, V> parent, Comparator ctr) {
+        Node<K, V> newNode = null;
         if (!isRed()) {
             if (0 > compare(parent.getKey(), ctr)) { //自身がどちらの子かを調べる
                 boolean rightChild = parent.left().right().isRed();
@@ -153,22 +141,33 @@
 
                 if (!parent.isRed()) { //親が黒
                     if (!parent.left().isRed()) { //左の子が黒
-                        if (!rightChild && !leftChild)
-                            throw new RotateParent(rebuildThree(parent, Rotate.R));
-                        if (rightChild)
-                            return rebuildfive(parent, Rotate.R);
-                        else
-                            return rebuildsix(parent, Rotate.R);
+                        if (!rightChild && !leftChild) {
+                            newNode = rebuildThree(parent, Rotate.R);
+                            return new Taple<>(true, newNode);
+                        }
+                        if (rightChild) {
+                            newNode = rebuildfive(parent, Rotate.R);
+                            return new Taple<>(false, newNode);
+                        } else {
+                            newNode = rebuildsix(parent, Rotate.R);
+                            return new Taple<>(false, newNode);
+                        }
                     } else { //左の子が赤
-                        return rebuildTwo(parent, ctr, Rotate.R);
+                        newNode = rebuildTwo(parent, ctr, Rotate.R);
+                        return new Taple<>(false, newNode);
                     }
                 } else { //親が赤
-                    if (!rightChild && !leftChild)
-                        return rebuildFour(parent, Rotate.R);
-                    if (rightChild)
-                        return rebuildfive(parent, Rotate.R);
-                    else
-                        return rebuildsix(parent, Rotate.R);
+                    if (!rightChild && !leftChild) {
+                        newNode = rebuildFour(parent, Rotate.R);
+                        return new Taple<>(false, newNode);
+                    }
+                    if (rightChild) {
+                        newNode = rebuildfive(parent, Rotate.R);
+                        return new Taple<>(false, newNode);
+                    } else {
+                        newNode = rebuildsix(parent, Rotate.R);
+                        return new Taple<>(false, newNode);
+                    }
                 }
             } else {
                 boolean rightChild = parent.right().right().isRed();
@@ -176,44 +175,60 @@
 
                 if (!parent.isRed()) { //親が黒
                     if (!parent.right().isRed()) { //左の子が黒
-                        if (!rightChild && !leftChild)
-                            throw new RotateParent(rebuildThree(parent, Rotate.L));
-                        if (rightChild)
-                            return rebuildsix(parent, Rotate.L);
-                        else
-                            return rebuildfive(parent, Rotate.L);
+                        if (!rightChild && !leftChild) {
+                            newNode = rebuildThree(parent, Rotate.L);
+                            return new Taple<>(true, newNode);
+                        }
+                        if (rightChild) {
+                            newNode = rebuildsix(parent, Rotate.L);
+                            return new Taple<>(false, newNode);
+                        } else {
+                            newNode = rebuildfive(parent, Rotate.L);
+                            return new Taple<>(false, newNode);
+                        }
                     } else { //左の子が赤
-                        return rebuildTwo(parent, ctr, Rotate.L);
+                        newNode = rebuildTwo(parent, ctr, Rotate.L);
+                        return new Taple<>(false, newNode);
                     }
                 } else { //親が赤
-                    if (!rightChild && !leftChild)
-                        return rebuildFour(parent, Rotate.L);
-                    if (rightChild)
-                        return rebuildsix(parent, Rotate.L);
-                    else
-                        return rebuildfive(parent, Rotate.L);
+                    if (!rightChild && !leftChild) {
+                        newNode = rebuildFour(parent, Rotate.L);
+                        return new Taple<>(false, newNode);
+                    }
+                    if (rightChild) {
+                        newNode = rebuildsix(parent, Rotate.L);
+                        return new Taple<>(false, newNode);
+                    } else {
+                        newNode = rebuildfive(parent, Rotate.L);
+                        return new Taple<>(false, newNode);
+                    }
                 }
             }
         }
-        if (0 > (compare(parent.getKey(), ctr)))
-            return parent.createNode(parent.getKey(), parent.getValue(), parent.left(), this);
-        else
-            return parent.createNode(parent.getKey(), parent.getValue(), this, parent.right());
+        if (0 > (compare(parent.getKey(), ctr))) {
+            newNode = parent.createNode(parent.getKey(), parent.getValue(), parent.left(), this);
+            return new Taple<>(false, newNode);
+        } else {
+            newNode = parent.createNode(parent.getKey(), parent.getValue(), this, parent.right());
+            return new Taple<>(false, newNode);
+        }
     }
 
-    protected Node<K, V> rebuildTwo(Node<K, V> parent, Comparator ctr, Rotate side) throws RotateParent { // case2
+    protected Node<K, V> rebuildTwo(Node<K, V> parent, Comparator ctr, Rotate side) { // case2
         if (side == Rotate.L) { // rotate Left
             Node<K, V> node = parent.right();
             Node<K, V> leftSubTreeRoot = node.createNode(parent.getKey(), parent.getValue(), this, node.left()); // check
-            Node<K, V> leftNode = this.deleteBalance(leftSubTreeRoot, ctr);
+            Taple<K, V> taple = new Taple<>(false, leftSubTreeRoot);
+            Taple<K, V> leftNodeTaple = this.deleteBalance(taple.getNode(), ctr);
             Node<K, V> rightNode = node.right();
-            return parent.createNode(node.getKey(), node.getValue(), leftNode, rightNode);
+            return parent.createNode(node.getKey(), node.getValue(), leftNodeTaple.getNode(), rightNode);
         } else {  // rotate Right
             Node<K, V> node = parent.left();
             Node<K, V> rightSubTreeRoot = node.createNode(parent.getKey(), parent.getValue(), node.right(), this);
-            Node<K, V> rightNode = this.deleteBalance(rightSubTreeRoot, ctr);
+            Taple<K, V> rightSubTreeTaple = new Taple<>(false, rightSubTreeRoot);
+            Taple<K, V> rightNodeTaple = this.deleteBalance(rightSubTreeTaple.getNode(), ctr);
             Node<K, V> leftNode = node.left();
-            return parent.createNode(node.getKey(), node.getValue(), leftNode, rightNode);
+            return parent.createNode(node.getKey(), node.getValue(), leftNode, rightNodeTaple.getNode());
         }
     }
 
@@ -284,9 +299,9 @@
 
     abstract boolean isRed();
 
-    public abstract Node<K, V> replaceNode(Node<K, V> parent, Comparator ctr) throws RotateParent;
+    public abstract Taple replaceNode(Node<K, V> parent, Comparator ctr);
 
-    protected abstract Node deleteNode() throws RotateParent;
+    protected abstract Taple deleteNode();
 
     @Test
     // test method
--- a/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/data/treemap/RedNode.java	Tue Sep 01 05:04:38 2015 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/data/treemap/RedNode.java	Tue Sep 01 16:09:08 2015 +0900
@@ -29,8 +29,9 @@
     }
 
     @Override
-    protected Node<K, V> deleteNode() throws RotateParent {
-        return new EmptyNode<>(this.getKey());
+    protected Taple deleteNode() {
+        Node emptyNode = new EmptyNode<>(this.getKey());
+        return new Taple(false, emptyNode);
     }
 
     @Override
@@ -57,16 +58,16 @@
 
     @SuppressWarnings("unchecked")
     @Override
-    public Node<K, V> replaceNode(Node<K, V> parent, Comparator ctr) throws RotateParent {
+    public Taple replaceNode(Node<K, V> parent, Comparator ctr) {
         Node<K, V> newNode;
         if (!this.left().isNotEmpty() && !this.right().isNotEmpty()) { //自身を削除する
             return deleteNode();
         } else if (this.left().isNotEmpty() && !this.right().isNotEmpty()) { //左の部分木を昇格させる
             newNode = left().createNode(left().getKey(), left().getValue(), left().left(), left().right());
-            return newNode;
+            return new Taple(false, newNode);
         } else if (!this.left().isNotEmpty() && this.right().isNotEmpty()) { //右の部分木を昇格させる
             newNode = right().createNode(right().getKey(), right().getValue(), right().left(), right().right());
-            return newNode;
+            return new Taple(false, newNode);
         } else {//子ノードが左右にある場合
             //左の部分木の最大の値を持つNodeと自身を置き換える
             Node<K, V> cur = this.left();
@@ -74,27 +75,26 @@
             while (cur.right().isNotEmpty()) {
                 cur = cur.right();
             }
-            Node<K, V> leftSubTreeNode;
             if (this.left().right().isNotEmpty()) {
-                try {
-                    leftSubTreeNode = this.left().deleteSubTreeMaxNode(null, ctr, Rotate.L);
-                    newNode = createNode(cur.getKey(), cur.getValue(), leftSubTreeNode, this.right());
-                    return newNode;
-                } catch (RotateParent e) {
-                    leftSubTreeNode = e.getParent();
-                    Node<K, V> newParent = createNode(cur.getKey(), cur.getValue(), leftSubTreeNode, this.right());
-                    return leftSubTreeNode.deleteBalance(newParent, ctr);
+                Taple<K, V> leftSubTreeNodeTaple = this.left().deleteSubTreeMaxNode(null, ctr, Rotate.L);
+                if (leftSubTreeNodeTaple.rebuild()) {
+                    Node<K, V> node = leftSubTreeNodeTaple.getNode();
+                    Node<K, V> newParent = createNode(cur.getKey(), cur.getValue(), node, this.right());
+                    return node.deleteBalance(newParent, ctr);
                 }
+                Node<K, V> leftSubTreeNode = leftSubTreeNodeTaple.getNode();
+                newNode = createNode(cur.getKey(), cur.getValue(), leftSubTreeNode, this.right());
+                return new Taple<>(false, newNode);
             } else {
-                try {
-                    leftSubTreeNode = this.left().replaceNode(this, ctr);
-                    newNode = createNode(cur.getKey(), cur.getValue(), leftSubTreeNode, this.right());
-                    return newNode;
-                } catch (RotateParent e) {
-                    Node<K, V> node = e.getParent();
+                Taple<K, V> leftSubTreeNodeTaple = this.left().replaceNode(this, ctr);
+                if (leftSubTreeNodeTaple.rebuild()) {
+                    Node<K, V> node = leftSubTreeNodeTaple.getNode();
                     Node<K, V> newParent = createNode(this.left().getKey(), this.left().getValue(), node, this.right());
                     return node.deleteBalance(newParent, ctr);
                 }
+                Node<K, V> leftSubTreeNode = leftSubTreeNodeTaple.getNode();
+                newNode = createNode(cur.getKey(), cur.getValue(), leftSubTreeNode, this.right());
+                return new Taple<>(false, newNode);
             }
 
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/data/treemap/Taple.java	Tue Sep 01 16:09:08 2015 +0900
@@ -0,0 +1,24 @@
+package jp.ac.u_ryukyu.ie.cr.jungle.data.treemap;
+
+
+public class Taple<K,V> {
+    private final Boolean rebuild;
+    private final Node<K,V> node;
+
+    public Taple(Boolean l,Node<K,V> node){
+        this.rebuild = l;
+        this.node = node;
+    }
+
+    public boolean rebuild(){
+        return rebuild;
+    }
+
+    public Node<K,V> getNode(){
+        return node;
+    }
+
+    public Boolean notEmpty(){
+        return node != null;
+    }
+}
--- a/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/data/treemap/TreeMap.java	Tue Sep 01 05:04:38 2015 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/data/treemap/TreeMap.java	Tue Sep 01 16:09:08 2015 +0900
@@ -53,17 +53,15 @@
 
 
     public TreeMap<K, V> delete(K key) {
-        Node<K, V> node = null;
-        try {
-            node = root.delete(key, null, comparator, Rotate.N);
-        } catch (RotateParent rotateParent) {
-            System.out.println("no call this scope");
-        }
-        if (node == null)
+        if (key == null)
+            return this;
+        Taple<K,V> rootTaple = root.delete(key, null, comparator, Rotate.N);
+        if (!rootTaple.notEmpty())
             return this; // not key
-        if (!node.isNotEmpty())
+        Node<K,V> root = rootTaple.getNode();
+        if (!root.isNotEmpty())
             return new TreeMap<>(new EmptyNode<>(), this.comparator);
-        Node<K, V> newRoot = new BlackNode<>(node.getKey(), node.getValue(), node.left(), node.right());
+        Node<K, V> newRoot = new BlackNode<>(root.getKey(), root.getValue(), root.left(), root.right());
         return new TreeMap<>(newRoot, this.comparator);
     }