赤黒木＋graphivizによる可視化

アルゴリズムイントロダクションに載ってる赤黒木を実装C#で実装してみました。
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();
        }
        
    }
}
```