using System.Collections; using System; using UnityEngine; using System.Collections.Generic; public abstract class TreeMapNode { protected K key = default(K); protected V value = default(V); public TreeMapNode right; public TreeMapNode left; // Use this for initialization public TreeMapNode (K key, V value) { this.key = key; this.value = value; } public TreeMapNode (K key, V value, TreeMapNode left, TreeMapNode right) { this.key = key; this.value = value; this.right = right; this.left = left; } public virtual TreeMapNode lefts () { return left; } public int compare(K compareKey, Comparer ctr) { int val = (int) ctr.Compare (compareKey, this.getKey ()); return val; } public V get (K key, Comparer ctr) { TreeMapNode cur = this; while (cur.isNotEmpty ()) { // getでEmpty nodeを返している ? compareでKeyが0になっている int result = cur.compare (key, ctr); if (result > 0) { cur = cur.rights (); } else if (result < 0) { cur = cur.lefts (); } else if (result == 0) { if (cur != null) { return cur.getValue (); } } } return default(V); } public virtual TreeMapNode rights () { return right; } public K getKey () { return key; } public V getValue () { return value; } // may be to use Comparer?? public TreeMapNode put (K k, V v,Comparer ctr) { if (!isNotEmpty ()) { return createNode (k, v, left, right); } int result = compare (k, ctr); if (result > 0) { TreeMapNode node = right.put (k, v, ctr); node = createNode (key, this.value, left, node); return node.insBalance (); } else if (result < 0) { TreeMapNode node = left.put (k, v,ctr); return createNode (key, this.value, node, right).insBalance (); } return createNode (key, v, left, right); } public rebuildNode delete (K key, TreeMapNode parent, Comparer ctr, Rotate side) { if (this.isNotEmpty ()) { rebuildNode rebuildNode = null; int result = compare(key, ctr); if (result > 0) { rebuildNode = right.delete (key, this, ctr, Rotate.R); } else if (result < 0) { rebuildNode = left.delete (key, this, ctr, Rotate.L); } else if (result == 0){ rebuildNode = replaceNode (parent, ctr); } if (parent == null) { return rebuildNode; } TreeMapNode node = rebuildNode.getNode (); if (rebuildNode.rebuilds ()) { // ここのエラーは後で return node.deleteBalance (parent, ctr); } TreeMapNode newParent; if (side == Rotate.L) { newParent = parent.createNode (parent.getKey (), parent.getValue (), node, parent.rights ()); } else { newParent = parent.createNode (parent.getKey (), parent.getValue (), parent.lefts (), node); } return new rebuildNode (false, newParent); } return null; } public rebuildNode deleteSubTreeMaxNode (TreeMapNode parent, Comparer ctr, Rotate side) { rebuildNode rebuildNode; TreeMapNode node; if (rights ().isNotEmpty ()) {// 最大値のノードが取得できるまで潜る rebuildNode = rights ().deleteSubTreeMaxNode (this, ctr, Rotate.R); } else { rebuildNode = this.replaceNode (parent, ctr); } if (parent == null) return rebuildNode; if (rebuildNode.rebuilds ()) { node = rebuildNode.getNode (); return node.deleteBalance (parent, ctr); } if (side == Rotate.R) node = parent.createNode (parent.getKey (), parent.getValue (), parent.lefts (), rebuildNode.getNode ()); else node = parent.createNode (parent.getKey (), parent.getValue (), rebuildNode.getNode (), parent.rights ()); return new rebuildNode (false, node); } public rebuildNode deleteBalance (TreeMapNode parent, Comparer ctr) { TreeMapNode newNode = null; if (!isRed ()) { if (0 > compare (parent.getKey (), ctr)) { bool rightChild = parent.lefts ().rights ().isRed (); bool leftChild = parent.lefts ().lefts ().isRed (); if (!parent.isRed ()) { if (!parent.lefts ().isRed ()) { if (!rightChild && !leftChild) { newNode = rebuildThree (parent, Rotate.R); return new rebuildNode (true, newNode); } if (rightChild) { newNode = rebuildfive (parent, Rotate.R); return new rebuildNode (false, newNode); } else { newNode = rebuildsix (parent, Rotate.R); return new rebuildNode (false, newNode); } } else { // 左の子が赤 newNode = rebuildTwo (parent, ctr, Rotate.R); return new rebuildNode (false, newNode); } } else { // 親が赤 if (!rightChild && !leftChild) { newNode = rebuildFour (parent, Rotate.R); return new rebuildNode (false, newNode); } if (rightChild) { newNode = rebuildfive (parent, Rotate.R); return new rebuildNode (false, newNode); } else { newNode = rebuildsix (parent, Rotate.R); return new rebuildNode (false, newNode); } } } else { bool rightChild = parent.rights ().rights ().isRed (); bool leftChild = parent.rights ().lefts ().isRed (); if (!parent.isRed ()) { // 親が黒 if (!parent.rights ().isRed ()) { // 左の子が黒 if (!rightChild && !leftChild) { newNode = rebuildThree (parent, Rotate.L); return new rebuildNode (true, newNode); } if (rightChild) { newNode = rebuildsix (parent, Rotate.L); return new rebuildNode (false, newNode); } else { newNode = rebuildfive (parent, Rotate.L); return new rebuildNode (false, newNode); } } else { // 左の子が赤 newNode = rebuildTwo (parent, ctr, Rotate.L); return new rebuildNode (false, newNode); } } else { // 親が赤 if (!rightChild && !leftChild) { newNode = rebuildFour (parent, Rotate.L); return new rebuildNode (false, newNode); } if (rightChild) { newNode = rebuildsix (parent, Rotate.L); return new rebuildNode (false, newNode); } else { newNode = rebuildfive (parent, Rotate.L); return new rebuildNode (false, newNode); } } } } if (0 > (compare (parent.getKey (), ctr))) { newNode = parent.createNode (parent.getKey (), parent.getValue (), parent.lefts (), this); return new rebuildNode (false, newNode); } else { newNode = parent.createNode (parent.getKey (), parent.getValue (), this, parent.rights ()); return new rebuildNode (false, newNode); } } protected TreeMapNode rebuildTwo (TreeMapNode parent, Comparer ctr, Rotate side) { // case2 if (side == Rotate.L) { // rotate Left TreeMapNode node = parent.rights (); TreeMapNode leftSubTreeRoot = node.createNode (parent.getKey (), parent.getValue (), this, node.lefts ()); // check rebuildNode rebuildNode = new rebuildNode (false, leftSubTreeRoot); rebuildNode leftNodeRebuildNode = this.deleteBalance (rebuildNode.getNode (), ctr); TreeMapNode rightNode = node.rights (); return parent.createNode (node.getKey (), node.getValue (), leftNodeRebuildNode.getNode (), rightNode); } else { // rotate Right TreeMapNode node = parent.lefts (); TreeMapNode rightSubTreeRoot = node.createNode (parent.getKey (), parent.getValue (), node.rights (), this); rebuildNode rightSubTreeRebuildNode = new rebuildNode (false, rightSubTreeRoot); rebuildNode rightNodeRebuildNode = this.deleteBalance (rightSubTreeRebuildNode.getNode (), ctr); TreeMapNode leftNode = node.lefts (); return parent.createNode (node.getKey (), node.getValue (), leftNode, rightNodeRebuildNode.getNode ()); } } protected TreeMapNode rebuildThree (TreeMapNode parent, Rotate side) { // case3 再帰 if (side == Rotate.L) { TreeMapNode rightNode; if (parent.rights ().isNotEmpty ()) rightNode = new RedNode (parent.rights ().getKey (), parent.rights ().getValue (), parent.rights ().lefts (), parent.rights ().rights ()); // check else rightNode = new EmptyNode (); return parent.createNode (parent.getKey (), parent.getValue (), this, rightNode); } else { TreeMapNode leftNode; if (parent.lefts ().isNotEmpty ()) leftNode = new RedNode (parent.lefts ().getKey (), parent.lefts ().getValue (), parent.lefts ().lefts (), parent.lefts ().rights ()); // check else leftNode = new EmptyNode (); return parent.createNode (parent.getKey (), parent.getValue (), leftNode, this); } } protected TreeMapNode rebuildFour (TreeMapNode parent, Rotate side) { // case 4 if (side == Rotate.R) { TreeMapNode leftNode = new RedNode (parent.lefts ().getKey (), parent.lefts ().getValue (), parent.lefts ().lefts (), parent.lefts ().rights ()); return new BlackNode (parent.getKey (), parent.getValue (), leftNode, this); } else { TreeMapNode rightNode = new RedNode (parent.rights ().getKey (), parent.rights ().getValue (), parent.rights ().lefts (), parent.rights ().rights ()); return new BlackNode (parent.getKey (), parent.getValue (), this, rightNode); } } protected TreeMapNode rebuildfive (TreeMapNode parent, Rotate side) { // case5 if (side == Rotate.R) { // rotate Left TreeMapNode leftChild = new RedNode (parent.lefts ().getKey (), parent.lefts ().getValue (), parent.lefts ().lefts (), parent.lefts ().rights ().lefts ()); TreeMapNode rightChild = parent.lefts ().rights ().rights (); TreeMapNode leftSubTreeRoot = new BlackNode (parent.lefts ().rights ().getKey (), parent.lefts ().rights ().getValue (), leftChild, rightChild); TreeMapNode newParent = parent.createNode (parent.getKey (), parent.getValue (), leftSubTreeRoot, this); return this.rebuildsix (newParent, Rotate.R); } else { // rotate Right 修正済み TreeMapNode leftChild = parent.rights ().lefts ().lefts (); TreeMapNode rightChild = new RedNode (parent.rights ().getKey (), parent.rights ().getValue (), parent.rights ().lefts ().rights (), parent.rights ().rights ()); TreeMapNode rightSubTreeRoot = new BlackNode (parent.rights ().lefts ().getKey (), parent.rights ().lefts ().getValue (), leftChild, rightChild); TreeMapNode newParent = parent.createNode (parent.getKey (), parent.getValue (), this, rightSubTreeRoot); return this.rebuildsix (newParent, Rotate.L); } } protected TreeMapNode rebuildsix (TreeMapNode parent, Rotate side) { // case6 if (side == Rotate.L) { // rotate Left TreeMapNode leftChild = parent.rights ().createNode (parent.getKey (), parent.getValue (), this, parent.rights ().lefts ()); // check TreeMapNode rightChild = new BlackNode (parent.rights ().rights ().getKey (), parent.rights ().rights ().getValue (), parent.rights ().rights ().lefts (), parent.rights ().rights ().rights ()); return parent.createNode (parent.rights ().getKey (), parent.rights ().getValue (), leftChild, rightChild); } else { // rotate Right TreeMapNode leftChild = new BlackNode (parent.lefts ().lefts ().getKey (), parent.lefts ().lefts ().getValue (), parent.lefts ().lefts ().lefts (), parent.lefts ().lefts ().rights ()); TreeMapNode rightChild = parent.lefts ().createNode (parent.getKey (), parent.getValue (), parent.lefts ().rights (), this); return parent.createNode (parent.lefts ().getKey (), parent.lefts ().getValue (), leftChild, rightChild); } } public abstract bool isNotEmpty (); public abstract TreeMapNode createNode (K key, V value, TreeMapNode left, TreeMapNode right); public abstract TreeMapNode insBalance (); public abstract Rotate checkRotate (Rotate side); public abstract bool isRed (); public abstract rebuildNode replaceNode (TreeMapNode parent, Comparer ctr); public abstract rebuildNode deleteNode (); // test method public abstract int checkDepth (int count, int minCount); }