【问题标题】:Generic hashtable method doesn't work correctly in C#通用哈希表方法在 C# 中无法正常工作
【发布时间】:2013-11-19 21:04:54
【问题描述】:

我正在尝试在 C# 中实现哈希表。到目前为止,这是我所拥有的:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GenericHashMap.hashtable
{
    class GenericHashtable<T>
    {

        private List<Node<T>> array;
        private int capacity;

        public GenericHashtable(int capacity)
        {
            this.capacity = capacity;
            array = new List<Node<T>>(capacity);
            for (int i = 0; i < capacity; i++)
            {
                array.Insert(i, null);
            }
        }

        public class Node<E>
        {
            private E info;
            private Node<E> next;

            public Node(E info, Node<E> next)
            {
                this.info = info;
                this.next = next;
            }

            public E Info
            {
                get
                {
                    return this.info;
                }
                set
                {
                    this.info = value;
                }
            }

            public Node<E> Next
            {
                get
                {
                    return this.next;
                }
                set
                {
                    this.next = value;
                }
            }
        }

        public bool IsEmpty()
        {
            if (array.Count == 0)
            {
                return true;
            }
            return false;
        }

        public void Add(T element)
        {
            int index = Math.Abs(element.GetHashCode() % capacity);
            Node<T> ToAdd = new Node<T>(element, null);
            Console.WriteLine("index = " + index);

            if (array.ElementAt(index) == null)
            {
                array.Insert(index, ToAdd);
                Console.WriteLine("The element " + array.ElementAt(index).Info.ToString() + " was found at index " + index);
            }
            else
            {
                Node<T> cursor = array.ElementAt(index);
                while (cursor.Next != null)
                {
                    cursor = cursor.Next;
                }
                if (cursor.Next == null)
                {
                    cursor.Next = ToAdd;
                    Console.WriteLine("The element " + array.ElementAt(index).Info.ToString() + " was found at index " + index);
                }
            }
        }

        public bool Search(T key)
        {
            int index = Math.Abs(key.GetHashCode() % capacity);
            Console.WriteLine("Index = " + index);
            Console.WriteLine("The element " + array.ElementAt(index).Info.ToString());

            if (array.ElementAt(index) == null)
            {
                return false;
            }
            else
            {
                if (array.ElementAt(index).Equals(key))
                {
                    Console.WriteLine("The element " + key + "exists in the map at index " + index);
                    return true;
                }
                else
                {
                    Node<T> cursor = array.ElementAt(index);
                    while (cursor != null && !(cursor.Info.Equals(key)))
                    {
                        cursor = cursor.Next;
                    }
                    if (cursor.Info.Equals(key))
                    {
                        Console.WriteLine("The " + key + "exists in the map");
                        return true;
                    }
                }
            }

            return false;
        }

        public void PrintElements()
        {
            for (int i = 0; i < capacity; i++)
            {
                Node<T> cursor = array.ElementAt(i);
                while (cursor != null)
                {
                    Console.WriteLine(cursor.Info.ToString());
                    cursor = cursor.Next;
                }
            }
        }
    }
}

现在,我在表格中添加以下字符串:

GenericHashtable<string> table = new GenericHashtable<string>(11);
            table.Add("unu"); -> index 3
            table.Add("doi"); -> index 0
            table.Add("trei"); -> index 6
            table.Add("patru"); -> index 7
            table.Add("cinci"); -> index 2
            table.Add("sase"); -> index 0

现在,一切都很好,元素已添加。但是当我试图搜索元素“unu”时,它没有找到,因为它的索引不再是 3,而是 5。“trei”的索引不是 6,而是 7……我不明白为什么元素正在改变它们的索引。我想在 Add() 方法中添加元素时出了点问题,但我自己不知道是什么。有答案吗?

【问题讨论】:

  • 为什么又被标记为 [java]?
  • @hexafraction 对不起,我的错。
  • 我只是想验证一下,这是为了研究目的吧?
  • 您似乎已将哈希表建模为列表,并且在添加某些内容时,您将项目 插入 到链接列表中(参见array.Insert(index, ToAdd);),因此 将表格的其余部分移回

标签: c# search hashtable add


【解决方案1】:

这是问题所在,在您的 Add 方法中:

array.Insert(index, ToAdd);

您的 array 变量实际上不是一个数组 - 它是一个列表。您正在向其中插入 元素,而不仅仅是设置现有元素。这将影响所有具有更高索引的现有元素 - 增加它们的索引。

我建议改用数组,只使用索引器:

private Node<T>[] nodes;

然后:

Node<T> node = nodes[index];
if (node == null)
{
    nodes[index] = newNode;
}
...

(说实话,代码还有很多其他奇怪的地方,但这就是当前问题的原因。)

【讨论】:

  • 那么在添加项目时,是否应该像StringBuilder 那样主动扩展数组以确保索引可用性?
  • @JonSkeet 所以,如果不切换到 Node[] 就没有办法解决这个问题?
  • @MoldovanRazvan,基于他的分析;如果您想继续使用List,您可以从插入索引开始重新索引整个列表,但这有点违背了目的。 :D
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-07-12
  • 1970-01-01
  • 1970-01-01
  • 2012-07-05
  • 1970-01-01
  • 1970-01-01
  • 2013-08-30
相关资源
最近更新 更多