アルゴリズムイントロダクションに載ってる赤黒木を実装C#で実装してみました。
C#よくわかっていません。
RBTree.rb
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;
namespace ConsoleApplication
//namespace RBTree
{
enum Color
{
RED,
BLACK
}
class Node
{
internal Node p;
internal Node left;
internal Node right;
public int key;
public Color color;
public Node(int key_)
{
this.key = key_;
this.p = null;
this.left = null;
this.right = null;
this.color = Color.BLACK;
}
public void setColor(Color c)
{
if (c == Color.BLACK)
{
// Console.WriteLine("{0} [style = filled, fillcolor = #CCCCCC];", this.key);
}
else
{
// Console.WriteLine("{0} [style = filled, fillcolor = #CC9999];", this.key);
}
this.color = c;
}
}
class RBTree
{
public Node root;
public Node nil;
public RBTree()
{
this.nil = null;
}
public void leftRotate(Node x)
{
Node y = x.right;
// βの付け替え
x.right = y.left;
if (y.left != nil)
{
y.left.p = x;
}
//yの親とのリンク
y.p = x.p;
if (x.p == nil)
{
root = y;
}
else if (x == x.p.left)
{
x.p.left = y;
}
else
{
x.p.right = y;
}
y.left = x;
x.p = y;
}
public void rightRotate(Node y)
{
Node x = y.left;
// βの付け替え
y.left = x.right;
if (x.right != nil)
{
x.right.p = y;
}
//yの親とのリンク
x.p = y.p;
if (y.p == null)
{
root = x;
}
else if (y == y.p.left)
{
y.p.left = x;
}
else
{
y.p.right = x;
}
x.right = y;
y.p = x;
}
public void insert(Node z)
{
Node y = nil;
Node x = root;
while (x != nil)
{
y = x;
if (z.key < x.key)
{
x = x.left;
}
else
{
x = x.right;
}
}
z.p = y;
if (y == nil) {
root = z;
}
else if (z.key < y.key)
{
y.left = z;
}
else
{
y.right = z;
}
z.left = nil;
z.right = nil;
z.color = Color.RED;
insertFixup(z);
}
public void insertFixup(Node z)
{
while (z.p.color == Color.RED)
{
if (z.p == z.p.p.left)
{
Node y = z.p.p.right;
if (y.color == Color.RED)
{
z.p.color = Color.BLACK;
y.color = Color.BLACK;
z.p.p.color = Color.RED;
z = z.p.p;
Console.WriteLine("case 1");
printGraphivz();
}
else{
if (z == z.p.right)
{
z = z.p;
this.leftRotate(z);
Console.WriteLine("case 2");
printGraphivz();
}
z.p.color = Color.BLACK;
z.p.p.color = Color.RED;
rightRotate(z.p.p);
Console.WriteLine("case 3");
printGraphivz();
}
}
else
{
Node y = z.p.p.left;
if (y.color == Color.RED)
{
z.p.color = Color.BLACK;
y.color = Color.BLACK;
z.p.p.color = Color.RED;
z = z.p.p;
Console.WriteLine("case 1");
printGraphivz();
}
else {
if (z == z.p.left)
{
z = z.p;
this.leftRotate(z);
Console.WriteLine("case 2");
printGraphivz();
}
z.p.color = Color.BLACK;
z.p.p.color = Color.RED;
rightRotate(z.p.p);
Console.WriteLine("case 3");
printGraphivz();
}
}
}
root.color = Color.BLACK;
printGraphivz();
}
public Node minimum(Node x)
{
while (x.left != nil)
{
x = x.left;
}
return x;
}
public Node successor(Node x)
{
if (x.right != nil) {
return minimum(x.right);
}
Node y = x.p;
while (y != nil && x == y.right) {
x = y;
y = y.p ;
}
return y;
}
public Node delete(Node z)
{
Node y;
if (z.left == nil || z.right == nil)
{
y = z;
}
else {
y = successor(z);
}
Node x;
if (y.left != nil) {
x=y.left;
}
else {
x = y.right;
}
if (x != nil) {
x.p = y.p;
}
if (y.p == nil) {
root = x;
}
else if (y == y.p.left) {
y.p.left = x;
}
else {
y.p.right = x;
}
if (y != z) {
z.key = y.key;
}
return y;
}
public void print()
{
Action<Node> loop = null;
loop = (Node x) =>
{
if (x != nil)
{
loop(x.left);
Console.WriteLine("{0}", x.key);
loop(x.right);
}
};
loop(root);
}
private string str(Color color)
{
if (color == Color.RED)
{
return "#CC9999";
}
else
{
return "#CCCCCC";
}
}
public void printGraphivz()
{
Action<Node> loop = null;
loop = (Node x) =>
{
if (x != nil)
{
Console.WriteLine("{0} [style = filled, fillcolor = \"{1}\"];", x.key, str(x.color));
if (x.left != nil)
{
Console.WriteLine("{0}->{1}[label = left];", x.key, x.left.key);
}
loop(x.left);
loop(x.right);
if (x.right != nil)
{
Console.WriteLine("{0}->{1}[label = right];", x.key, x.right.key);
}
if (x.p != nil)
{
Console.WriteLine("{0}->{1}[label = p];", x.key, x.p.key);
}
}
};
string filename = (DateTime.Now).ToString("ddHHmmssfff");
StreamWriter sw = new StreamWriter(String.Format("{0}.dot",filename), true, System.Text.Encoding.GetEncoding("utf-8")); // 文字コード
Console.SetOut(sw);
Console.WriteLine("strict digraph rbtrees{0} ",(DateTime.Now).ToString("ssfff"));
Console.WriteLine("{");
loop(root);
Console.WriteLine("}");
sw.Dispose();
System.IO.StreamWriter standard = new System.IO.StreamWriter(Console.OpenStandardOutput());
standard.AutoFlush = true;
Console.SetOut(standard);
System.Diagnostics.Process.Start("dot", string.Format("-Tpng {0}.dot -o {0}.png",filename,filename));
}
}
class Program
{
void test3()
{
Node n = new Node(15);
RBTree t = new RBTree();
t.root = n;
t.root.left = new Node(5);
t.root.left.p = t.root;
t.root.left.left = new Node(3);
t.root.left.left.p = t.root.left;
t.root.left.right = new Node(12);
t.root.left.right.p = t.root.left;
t.root.left.right.right = new Node(13);
t.root.left.right.right.p = t.root.left.right;
t.root.left.right.left= new Node(10);
t.root.left.right.left.p = t.root.left.right;
t.root.left.right.left.left = new Node(6);
t.root.left.right.left.left.p = t.root.left.right.left;
t.root.left.right.left.left.right = new Node(7);
t.root.left.right.left.left.right.p = t.root.left.right.left.left;
t.root.right = new Node(16);
t.root.right.p = t.root;
t.root.right.right = new Node(20);
t.root.right.right.p = t.root.right;
t.root.right.right.left = new Node(18);
t.root.right.right.left.p = t.root.right.right;
t.root.right.right.right = new Node(23);
t.root.right.right.right.p = t.root.right.right;
t.printGraphivz();
//t.delete (t.root.left.right.right);
//t.delete(t.root.right);
t.delete(t.root.left);
t.printGraphivz();
}
void test2()
{
Node n = new Node(11);
RBTree t = new RBTree();
t.root = n;
t.root.setColor(Color.BLACK);
t.root.left = new Node(2);
t.root.left.p = t.root;
t.root.left.setColor(Color.RED);
t.root.left.left = new Node(1);
t.root.left.left.p = t.root.left;
t.root.left.left.setColor(Color.BLACK);
t.root.left.right = new Node(7);
t.root.left.right.p = t.root.left;
t.root.left.right.setColor(Color.BLACK);
t.root.left.right.left = new Node(5);
t.root.left.right.left.p = t.root.left.right;
t.root.left.right.left.setColor(Color.RED);
t.root.left.right.left.left = new Node(4);
t.root.left.right.left.left.p = t.root.left.right.left;
t.root.left.right.left.left.setColor(Color.RED);
t.root.left.right.right = new Node(8);
t.root.left.right.right.p = t.root.left.right;
t.root.left.right.right.setColor(Color.RED);
t.root.right = new Node(14);
t.root.right.p = t.root;
t.root.right.setColor(Color.BLACK);
t.root.right.right = new Node(15);
t.root.right.right.p = t.root.right;
t.root.right.right.setColor(Color.RED);
t.printGraphivz();
t.insertFixup(t.root.left.right.left.left);
//Node n2 = new Node(4);
//n2.setColor(Color.RED);
//t.insert(n2);
//t.printGraphivz();
}
public void test1()
{
Node n = new Node(7);
RBTree t = new RBTree();
t.root = n;
t.root.left = new Node(4);
t.root.left.p = t.root;
t.root.left.left = new Node(3);
t.root.left.left.p = t.root.left;
//Console.WriteLine("{0}->{1}[label = p];", t.root.left.left.p.key, t.root.left.key);
t.root.left.left.left = new Node(2);
t.root.left.left.left.p = t.root.left.left;
t.root.left.right = new Node(6);
t.root.left.right.p = t.root.left;
t.root.right = new Node(11);
t.root.right.p = t.root;
t.root.right.left = new Node(9);
t.root.right.left.p = t.root.right;
t.root.right.right = new Node(18);
t.root.right.right.p = t.root.right;
t.root.right.right.left = new Node(14);
t.root.right.right.left.p = t.root.right.right;
t.root.right.right.left.left = new Node(12);
t.root.right.right.left.left.p = t.root.right.right.left;
t.root.right.right.left.right = new Node(17);
t.root.right.right.left.right.p = t.root.right.right.left;
t.root.right.right.right = new Node(19);
t.root.right.right.right.p = t.root.right.right;
t.root.right.right.right.right = new Node(22);
t.root.right.right.right.right.p = t.root.right.right.right;
t.root.right.right.right.right.left = new Node(20);
t.root.right.right.right.right.left.p = t.root.right.right.right.right;
//Console.WriteLine("}");
t.printGraphivz();
//t.print();
t.leftRotate(t.root.right);
t.printGraphivz();
t.rightRotate(t.root.right);
t.printGraphivz();
//t.print();
}
static void Main(string[] args)
{
Program p = new Program();
p.test3();
}
}
}