C#中的哈希表哈希函数实现

时间:2016-12-17 09:05:08

标签: c# arrays random hash hashtable

我有100-1001的随机数组,我转移到哈希表。 散列函数是n的mod(数组的大小)。 问题是,当我试图检查哈希表中的内容时,它向我显示了我在纸上计算的不同索引,所以我很困惑,如果它的工作正确与否。 另外,据我所知,哈希表的大小必须至少比数组大小大5%,但我找不到如何设置哈希表大小。我哪里弄错了? 我必须在此之后使用相同的哈希函数按地址搜索。

    static void Main()
    {

        int n;

        Console.WriteLine("Please enter array size");
        n = Convert.ToInt32(Console.ReadLine());

        Random rnd = new Random();
        int[] a = new int[n + 4];

        for (int i = 0; i < n; i++)
            Console.Write("{0,4}", a[i] = rnd.Next(100, 1001));    
        // I have deleted code in the middle as there is certain type of search in array which works fine

        // Now putting values to hash table       

        Hashtable Hashtable = new Hashtable();
        int hashcode = n + ((n / 100) * 5);
        int value; 
        int key;
        for (int i = 0; i < n; i++)
        {
            value = a[i];
            key = value % hashcode;

            if (Hashtable[key] == null)
                Hashtable.Add(key, value);
            else
            {
                while (Hashtable[key] != null)
                {
                    if (key == (hashcode - 1))
                        key = 0;
                    else
                        key++;
                }
                Hashtable.Add(key, value);
            }
        }

              Console.WriteLine();
    }

1 个答案:

答案 0 :(得分:1)

关于哈希表如何在.NET中运行,似乎有点混乱。哈希表是关联列表。这意味着您可以通过其键检索值,这在数组或列表不起作用时很有用,因为您不通过索引访问值(例如,在缓存方案中)。为了快速访问存储的键/值对,哈希表内部计算密钥的哈希码,以便将数据存储在桶中。

您正在做的是从外部计算“哈希码” ,然后将其用作哈希表的键。哈希表的作用是计算该键的哈希码 以存储键/值对。我很确定这不是你想要做的。

我通常会建议您使用Dictionary<int, int>,但您的情况有所不同。您的密钥直接来自您要存储的值,因此您的情况不适用于请求列表。我不确切地知道你想要实现什么,但你的情况看起来最适合HashSet(这是一个使用哈希码来存储值的集合)。您可以覆盖密钥的GetHashCode方法来更改散列方法,即使没有必要。在你的情况下,它甚至会降低哈希集的有效性,因为你的哈希方法不仅非常差,因为它的范围远远小于Int32的范围,它也会导致很多冲突,你的哈希集必须解决。

由于您无法更改GetHashCode的{​​{1}}方法,因此您必须为此创建一个包装器:

int

然后,您可以创建private struct HashCodeWrapper { private readonly int value; private readonly int n; public int Value { get { return value; } } public HashCodeWrapper(int value, int n) { this.value = value; this.n = n; } public override int GetHashCode() { return value % (n + ((n / 100) * 5)); } public override bool Equals(object obj) { return (obj is HashCodeWrapper) && ((HashCodeWrapper)obj).value.Equals(value); } } 并将包装器添加到集合中。如果这对您不起作用,您必须实现自己的“哈希表”版本。

但是出于所有实际目的,只需使用HashSet<HashCodeWrapper>并节省大量工作。