2012-02-19 10 views
1

私は、C#で実装されたディクショナリのようなジェネリックスを使用してハッシュテーブルを実装していますが、ハッシュ関数の部分に固執しています。私はsuccessufulyジェネリック1のハッシュテーブルの非ジェネリック実装を書き直しましたが、私はどのようにTkeyをハッシュするかわからないコードで気づくでしょう。一般ハッシュテーブルの実装で汎用キーをハッシュする方法は?

class Node<T, U> 
{ 
    public T key; 
    public U value; 
    public Node<T, U> next; 
    public Node(T key, U value, Node<T, U> next) 
    { 
     this.key = key; 
     this.value = value; 
     this.next = next; 
    } 
} 

public class HashTable<T,U> 
{ 
    int length; 
    Node<T,U>[] buckets; 
    public HashTable(int length) 
    { 
     this.length = length; 
     buckets = new Node<T,U>[length]; 
    } 

    public void Display() 
    { 
     for (int bucket = 0; bucket<buckets.Length; bucket++) 
     { 
      Node<T,U> current = buckets[bucket]; 
      Console.Write(bucket + ":"); 
      while (current != null) 
      { 
       Console.Write("["+current.key+","+current.value+"]"); 
       current=current.next; 
      } 
      Console.WriteLine(); 
     } 
    } 
    // private int Hash(T Tkey) ... 
    //// non-generic version of hash function 

    private int Hash(string str) 
    { 
     int h=0; 
     foreach(var s in str) 
      h=127*h+s; 
     return h%length; 

    } 
    //// 
    public void Insert(T key, U value) 
    { 
     int bucket = Hash(key); 
     buckets[bucket] = new Node<T,U>(key, value, buckets[bucket]); 
    } 
    public U Search(T key) 
    { 
     Node<T,U> current = buckets[Hash(key)]; 
     while (current != null) 
     { 
      if (current.key.Equals(key)) 
       return current.value; 
      current= current.next; 
     } 
     throw new Exception(key+ "Not found"); 
    } 
+0

これは[tag:java]ですか?その場合は、適切なタグを付けてください。 –

+0

*なぜあなたは独自の実装を書いていますか? – svick

答えて

3

C#でベースオブジェクトクラスは、これらの状況のた​​めに使用されるべきであるGetHashCode()方法が付属しています。

いくつかのクラスは実装が良好で、他のクラスはSystem.Objectからメソッドを継承しており、オーバーライドしません。

MSDNのドキュメントから:

GetHashCodeメソッドのデフォルトの実装が異なるオブジェクトの一意の戻り値を保証するものではありません。さらに、.NET FrameworkではGetHashCodeメソッドの既定の実装が保証されておらず、返される値は.NET Frameworkの異なるバージョン間で同じになります。したがって、このメソッドのデフォルトの実装は、ハッシングの目的で一意のオブジェクト識別子として使用されてはなりません。

GetHashCodeメソッドは、派生型でオーバーライドできます。値の型は、その型に適したハッシュ関数を提供し、ハッシュテーブルに有用な分布を提供するために、このメソッドをオーバーライドする必要があります。一意性のためには、ハッシュコードは静的なフィールドまたはプロパティではなく、インスタンスフィールドまたはプロパティの値に基づいている必要があります。

+0

自分のハッシュ関数を書くべきだと思います。まず第一に、GetHashCodeはバージョン間で同じ動作を生み出すことは保証されていません。また、GetHashCodeは負の値を返すことができるので、インデックスの範囲外のエラーが発生します。しかし、私が書いたのは:return Math.Abs​​(Tkey.GetHashCode());私のハッシュ関数の中に出力がありますが、これは愚かな解決策であると思います。ハッシュのアイデアは、衝突の可能性を減らすはずですが、私はこれで何が得られるのかよく分かりません。 –

+4

実際にGetHashCodeを使用する必要があります。オブジェクトが同じハッシュを返すかどうかを判断するのは依存オブジェクトの責任です。あなたの計画ではうまくいかないからといって問題ではありません。必要に応じて値を調整しますが、一貫して行います。 – Joe

+0

@impeRAtoR、バージョン間で同じ動作が必要なのはなぜですか?ここで 'Math.Abs​​()'を使うのはまったくばかげたことではありません。 'Dictionary'は非常に似たようなことをします。 – svick

関連する問題