【问题标题】:How to hash generic key in generic hash table implementation?如何在通用哈希表实现中散列通用键?
【发布时间】:2012-02-19 22:38:12
【问题描述】:

我正在使用泛型实现哈希表,例如在 c# 中实现的 Dictionary,但我被困在 Hash 函数部分。我成功地用泛型重写了哈希表的非泛型实现,但你会在代码中注意到我不知道如何散列 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");
    }

【问题讨论】:

  • 这是java吗?如果是这样,请适当标记。
  • 为什么你要编写自己的实现?

标签: c# .net function generics hash


【解决方案1】:

C# 中的基对象类带有 GetHashCode() 方法,应该用于这些情况。

有些类有很好的实现,有些类只是从System.Object继承方法而不覆盖它。

来自 MSDN 文档:

GetHashCode 方法的默认实现不保证不同对象的唯一返回值。此外,.NET Framework 不保证GetHashCode 方法的默认实现,它返回的值在不同版本的.NET Framework 之间是相同的。因此,此方法的默认实现不得用作散列目的的唯一对象标识符。

GetHashCode 方法可以被派生类型覆盖。值类型必须重写此方法以提供适合该类型的散列函数并在散列表中提供有用的分布。为了唯一性,哈希码必须基于实例字段或属性的值,而不是静态字段或属性。

【讨论】:

  • 我想我应该编写自己的哈希函数。首先,GetHashCode 不能保证在版本之间产生相同的行为。 GetHashCode 也可以返回负值,所以我得到 Index out of bounds 错误。但是,如果我写: return Math.Abs​​(Tkey.GetHashCode());在我的哈希函数中,我有一些输出,但我想这是愚蠢的解决方案。散列的想法应该是减少冲突的可能性,但我不确定我能得到什么。
  • 你真的应该使用GetHashCode;由依赖对象决定该对象是否返回相同的哈希值。仅仅因为它不适用于您的方案并不重要;根据需要调整值以满足您的要求,但要始终如一地这样做。
  • @impeRAtoR,为什么版本之间需要相同的行为?在这里使用Math.Abs() 一点也不傻。 Dictionary 做了非常相似的事情。
  • @impeRAtoR:如果GetHashCode 跨平台一致对您很重要,那么您做错了。如果您关心GetHashCode 返回负值,那么您做错了。 GetHashCode 用于生成可用于平衡哈希表的值。它们不用于任何其他目的,所以不要这样使用它们。
  • 从技术上讲,object 的实现不保证唯一值是对的。但这只是因为GetHashCode 的大多数实现也没有。当strings 比ints 多得多时,你怎么能保证两个不同的字符串具有不同的哈希码?
猜你喜欢
  • 1970-01-01
  • 2018-04-01
  • 2020-12-13
  • 1970-01-01
  • 2012-03-04
  • 2013-09-26
  • 2016-05-17
  • 2015-01-06
  • 1970-01-01
相关资源
最近更新 更多