using System.Collections.Generic; using System.Collections; using System; public class BlackNode :TreeMapNode { public BlackNode (K key, V value, TreeMapNode left, TreeMapNode right) : base (key, value, left, right) { } public override rebuildNode deleteNode () { EmptyNode emptyNode = new EmptyNode (key); return new rebuildNode (true, emptyNode); } public override int checkDepth (int count, int minCount) { // test method count++; minCount = lefts ().checkDepth (count, minCount); minCount = rights ().checkDepth (count, minCount); return minCount; } public override bool isNotEmpty () { return true; } public override TreeMapNode createNode (K key, V value, TreeMapNode left, TreeMapNode right) { return new BlackNode (key, value, left, right); } public override TreeMapNode insBalance () { Rotate spin = left.checkRotate (Rotate.L); if (spin == Rotate.R) { TreeMapNode leftChild = new BlackNode (left.lefts ().getKey (), left.lefts ().getValue (), left.lefts ().lefts (), left.lefts ().rights ()); TreeMapNode rightChild = new BlackNode (getKey (), getValue (), left.rights (), right); return new RedNode (left.getKey (), left.getValue (), leftChild, rightChild); } else if (spin == Rotate.LR) { TreeMapNode leftChild = new BlackNode (left.getKey (), left.getValue (), left.lefts (), left.rights ().lefts ()); TreeMapNode rightChild = new BlackNode (getKey (), getValue (), left.rights ().rights (), right); return new RedNode (left.rights ().getKey (), left.rights ().getValue (), leftChild, rightChild); } spin = right.checkRotate (Rotate.R); if (spin == Rotate.L) { TreeMapNode leftChild = new BlackNode (getKey (), getValue (), left, right.lefts ()); TreeMapNode rightChild = new BlackNode (right.rights ().getKey (), right.rights ().getValue (), right.rights ().lefts (), right.rights ().rights ()); return new RedNode (right.getKey (), right.getValue (), leftChild, rightChild); } else if (spin == Rotate.RL) { TreeMapNode leftChild = new BlackNode (getKey (), getValue (), left, right.lefts ().lefts ()); TreeMapNode rightChild = new BlackNode (right.getKey (), right.getValue (), right.lefts ().rights (), right.rights ()); return new RedNode (right.lefts ().getKey (), right.lefts ().getValue (), leftChild, rightChild); } return this; } public override Rotate checkRotate (Rotate side) { return Rotate.N; } public override bool isRed () { return false; } public override rebuildNode replaceNode (TreeMapNode parent, Comparer ctr) { TreeMapNode newNode; if (!this.lefts ().isNotEmpty () && !this.rights ().isNotEmpty ()) { //自身を削除する return deleteNode ();//黒が1つ減るので木のバランスを取る } else if (this.lefts ().isNotEmpty () && !this.rights ().isNotEmpty ()) { //左の部分木を昇格させる newNode = createNode (lefts ().getKey (), lefts ().getValue (), lefts ().lefts (), lefts ().rights ()); if (!this.lefts ().isRed ()) //昇格させる木のrootが黒だったらバランスを取る return new rebuildNode (true, newNode); return new rebuildNode (false, newNode); } else if (!this.lefts ().isNotEmpty () && this.rights ().isNotEmpty ()) { //右の部分木を昇格させる newNode = createNode (rights ().getKey (), rights ().getValue (), rights ().lefts (), rights ().rights ()); if (!this.rights ().isRed ()) //昇格させる木のrootが黒だったらバランスを取る return new rebuildNode (true, newNode); return new rebuildNode (false, newNode); } else {//子ノードが左右にある場合 二回目はここには入らない //左の部分木の最大の値を持つNodeと自身を置き換える TreeMapNode cur = this.lefts (); while (cur.rights ().isNotEmpty ()) { //左の部分期の最大値を持つNodeを取得する cur = cur.rights (); } if (this.lefts ().rights ().isNotEmpty ()) { //左の部分木が右の子を持っているか rebuildNode leftSubTreeNodeRebuildNode = this.lefts ().deleteSubTreeMaxNode (null, ctr, Rotate.L);//最大値を削除した左の部分木を返す。rootはthisと同じ。 if (leftSubTreeNodeRebuildNode.rebuilds ()) { TreeMapNode leftSubTreeNode = leftSubTreeNodeRebuildNode.getNode (); TreeMapNode newParent = createNode (cur.getKey (), cur.getValue (), leftSubTreeNode, this.rights ()); return leftSubTreeNode.deleteBalance (newParent, ctr); } //same name onece used. TreeMapNode leftSubTreeNodes = leftSubTreeNodeRebuildNode.getNode (); newNode = createNode (cur.getKey (), cur.getValue (), leftSubTreeNodes, this.rights ()); //rootをcurと入れ替えることでNodeの削除は完了する return new rebuildNode (false, newNode); } else { rebuildNode leftSubTreeNodeRebuildNode = this.lefts ().replaceNode (this, ctr);//右の子がいなかった場合、左の子を昇格させるだけで良い。 if (leftSubTreeNodeRebuildNode.rebuilds ()) { TreeMapNode node = leftSubTreeNodeRebuildNode.getNode (); TreeMapNode newParent = createNode (this.lefts ().getKey (), this.lefts ().getValue (), node, this.rights ()); return node.deleteBalance (newParent, ctr); } TreeMapNode leftSubTreeNode = leftSubTreeNodeRebuildNode.getNode (); newNode = createNode (this.lefts ().getKey (), this.lefts ().getValue (), leftSubTreeNode, this.rights ()); return new rebuildNode (false, newNode); } } } }