using System; using System.Collections.Generic; using System.Text; namespace Collections { /// /// ハッシュテーブル。 /// /// 要素の型 class HashTable : ISet { #region 内部クラス class Node { internal T val; internal Node next; internal Node(T val, Node next) { this.val = val; this.next = next; } } #endregion #region フィールド Node[] table; int mask; #endregion #region 初期化 public HashTable() : this(256) { } public HashTable(int capacity) { capacity = Pow2((uint)capacity); this.mask = capacity - 1; this.table = new Node[capacity]; } static int Pow2(uint n) { --n; int p = 0; for (; n != 0; n >>= 1) p = (p << 1) + 1; return p + 1; } #endregion #region 挿入・削除・検索 /// /// 要素の挿入。 /// /// 挿入する要素 public void Insert(T elem) { int code = elem.GetHashCode() & this.mask; Node n = this.table[code]; Node m = new Node(elem, n); m.next = n; this.table[code] = m; } /// /// 要素の削除。 /// /// 削除する要素 public void Erase(T elem) { int code = elem.GetHashCode() & this.mask; Node n = this.table[code]; if (n == null) return; if (n.next == null) this.table[code] = null; while (n.next != null && n.next.val.Equals(elem)) n = n.next; if(n.next != null) n.next = n.next.next; } /// /// テーブル中に要素が含まれているかどうか判別。 /// /// 探したい要素 /// 含まれていれば true public bool Contains(T elem) { int code = elem.GetHashCode() & this.mask; Node n = this.table[code]; while (n != null && !n.val.Equals(elem)) n = n.next; return n != null; } /// /// テーブル中の要素を検索。 /// /// 探したい要素 /// 含まれていればその要素を、なければ default(T) public T Find(T elem) { int code = elem.GetHashCode(); Node n = this.table[code & this.mask]; while (n != null && !n.val.Equals(elem)) n = n.next; if (n == null) return default(T); return n.val; } #endregion #region IEnumerable メンバ public IEnumerator GetEnumerator() { for (int i = 0; i < this.table.Length; ++i) for (Node n = this.table[i]; n != null; n = n.next) yield return n.val; } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return this.GetEnumerator(); } #endregion } }