C# 二分探索木
ごく一般的な二分探索木のC#による実装。AVL木のようにバランスはしない。
using System; public sealed class Node<TKey, TValue> where TKey : IComparable<TKey> { private TKey key; private TValue value; private Node<TKey, TValue> left; private Node<TKey, TValue> right; public Node(TKey key, TValue value) { this.key = key; this.value = value; this.left = null; this.right = null; } public TKey Key { get { return key; } set { key = value; } } public TValue Value { get { return value; } set { this.value = value; } } public Node<TKey, TValue> Left { get { return left; } set { left = value; } } public Node<TKey, TValue> Right { get { return right; } set { right = value; } } } public sealed class BinarySearchTree<TKey, TValue> where TKey : IComparable<TKey> { private Node<TKey, TValue> root = null; public Boolean Add(TKey key, TValue value) { if (root == null) { root = new Node<TKey, TValue>(key, value); return true; } Node<TKey, TValue> curr = root; while (true) { Int32 cond = key.CompareTo(curr.Key); if (cond < 0) { if (curr.Left == null) { curr.Left = new Node<TKey, TValue>(key, value); break; } else { curr = curr.Left; } } else if (cond > 0) { if (curr.Right == null) { curr.Right = new Node<TKey, TValue>(key, value); break; } else { curr = curr.Right; } } else { //キーは既に存在している return false; } } //追加成功 return true; } public Boolean Searech(TKey key, out TValue value) { Node<TKey, TValue> curr = root; while (curr != null) { Int32 cond = key.CompareTo(curr.Key); if (cond < 0) { curr = curr.Left; } else if (cond > 0) { curr = curr.Right; } else { value = curr.Value; return true; } } value = default(TValue); return false; } public Boolean Remove(TKey key) { Node<TKey, TValue> curr = root; Node<TKey, TValue> parent = null; Boolean goToLeftChild = true; while (true) { if (curr == null) { return false; } Int32 cond = key.CompareTo(curr.Key); if (cond == 0) { break; } else { parent = curr; if (cond < 0) { goToLeftChild = true; curr = curr.Left; } else { goToLeftChild = false; curr = curr.Right; } } } if (curr.Left == null) //左の子がない { if (curr == root) { } else if (goToLeftChild) { parent.Right = curr.Right; } else { parent.Right = curr.Right; } } else if (curr.Right == null) //右の子がない { if (curr == root) { root = curr.Left; } else if (goToLeftChild) { parent.Left = curr.Left; } else { parent.Right = curr.Left; } } else //子は2つ { parent = curr; Node<TKey, TValue> left = curr.Left; goToLeftChild = true; while (left.Right != null) { parent = left; left = left.Right; goToLeftChild = false; } curr.Key = left.Key; curr.Value = left.Value; if (goToLeftChild) { parent.Left = left.Left; } else { parent.Right = left.Left; } } return true; } private void PrintSubTree(Node<TKey, TValue> node) { if (node != null) { //左部分木をキー値昇順に表示 PrintSubTree(node.Left); //nodeを表示 Console.WriteLine("{0} {1}", node.Key, node.Value); //右部分木をキー値昇順に表示 PrintSubTree(node.Right); } } public void PrintTree() { PrintSubTree(root); } } class Program { static void Main() { BinarySearchTree<Int32, Int32> tree = new BinarySearchTree<Int32, Int32>(); tree.Add(50, 50); tree.Add(25, 25); tree.Add(75, 75); tree.Add(10, 10); tree.Add(20, 20); tree.Add(15, 15); tree.Add(100, 100); tree.Add(30, 30); tree.Add(70, 70); tree.Add(60, 60); tree.Add(65, 65); tree.Add(73, 73); tree.Add(74, 74); tree.PrintTree(); tree.Remove(75); Int32 value; if (tree.Searech(30, out value)) { Console.WriteLine(value); } } }