字典(散列表)和列表查找之间的权衡点

时间:2010-06-04 13:55:01

标签: c# search

简短的问题:列表中有多少个元素可以像List O(n)那样进行线性搜索,然后比字典O(1)更快?

我似乎记得在大学(和高中)比较搜索技术(二元与线性)时总是存在线性更快的点。那是O(n)vs O(log)

我无法在此处绘制图表。但是对于不断的表现必须有一些头脑。所以问题是我是否有10个项目List.Find更有意义

if (Dictionary.Contains(x))
    value = Directiory[x]

或Hashtable,其中value = Hashtable [x]不会失败,但需要装箱

5 个答案:

答案 0 :(得分:5)

我问自己同样的问题,然后跑了一个基准来找出答案。我发现字典的速度已经超过了 3-4个元素的查找列表。

根据字典的开销,这对我来说似乎很少,所以我查看是否有其他人发现相同的结果,这似乎是其他人发现的结果。 http://dotnetperls.com/dictionary-time

这并不意味着,将几十个字典扔进你的代码中它们没有意义 - 还有一个内存开销和构建时间来处理。但是如果你有一组体积适中的键控数据,那就利用这种结构。

答案 1 :(得分:1)

使用您的数据测试这两种方法并做出决定。

在您的收藏中只有10个项目,哈希的不变成本可能会超过查看列表中每个项目的成本(最坏的情况)。但是,我们不能肯定地说。测试并找出答案。

请记住,插入字典比插入List更昂贵。根据您使用收藏品的位置和方式,可能不需要额外的插入成本。

答案 2 :(得分:1)

因此,在对我自己进行一些测试后,看起来Hash-Dictionary总是获胜。这是一个带有HashCode的字对象,int32,作为键

10 items    500,000 itterations             
Test Name                                           First   Last    Not Found   Average 
FindInList                                          104.26  255.29  254.63      204.73
FindInArray                                         51.28   192.23  182.91      142.14
FindInHashDict                                      56.3    54.38   51.16       53.95
FindInDict                                          105.75  101.38  52.02       86.38

100 items   500,000 itterations             
Test Name                                           First   Last    Not Found   Average 
FindInList                                          102.83  1873.45 1820.85     1265.71
FindInArray                                         56.21   1313.61 1310.65     893.49
FindInHashDict                                      91.01   53.31   60.46       68.26
FindInDict                                          119.01  101.65  100.11      106.92

这是执行查找操作的代码。我的对象是分层任务,可以通过唯一名称进行搜索。我知道这是一个很长的帖子,但如果有人想对调查结果提出质疑,他们可以看到代码。

    private SearchResult FindInDict()
    {
        SearchResult result = new SearchResult();
        result.SeachType = "FindInDict";
        result.itterations = 1;

        Stopwatch timer = new Stopwatch();

        timer.Start();
        if (dictStrBoundryTask.ContainsKey(NameOfFirst))
        {
            TaskBase t = dictStrBoundryTask[NameOfFirst];
        }

        timer.Stop();

        result.firstItem = timer.Elapsed.TotalMilliseconds;

        timer.Reset();

        timer.Start();
        if (dictStrBoundryTask.ContainsKey(NameOfLast))
        {
            TaskBase t = dictStrBoundryTask[NameOfLast];
        }

        timer.Stop();

        result.lastItem = timer.Elapsed.TotalMilliseconds;

        timer.Reset();

        timer.Start();
        if (dictStrBoundryTask.ContainsKey(NameOfNotFound))
        {
            TaskBase t = dictStrBoundryTask[NameOfNotFound];
        }

        timer.Stop();

        result.notFoundItem = timer.Elapsed.TotalMilliseconds;

        return result;

    }

    private SearchResult FindInHashDict()
    {
        SearchResult result = new SearchResult();
        result.SeachType = "FindInHashDict";
        result.itterations = 1;

        Stopwatch timer = new Stopwatch();

        timer.Start();
        if (dictIntBoundryTask.ContainsKey(NameOfFirst.GetHashCode()))
        {
            TaskBase t = dictIntBoundryTask[NameOfFirst.GetHashCode()];
        }

        timer.Stop();

        result.firstItem = timer.Elapsed.TotalMilliseconds;

        timer.Reset();

        timer.Start();
        if (dictIntBoundryTask.ContainsKey(NameOfLast.GetHashCode()))
        {
            TaskBase t = dictIntBoundryTask[NameOfLast.GetHashCode()];
        }

        timer.Stop();

        result.lastItem = timer.Elapsed.TotalMilliseconds;

        timer.Reset();

        timer.Start();
        if (dictIntBoundryTask.ContainsKey(NameOfNotFound.GetHashCode()))
        {
            TaskBase t = dictIntBoundryTask[NameOfNotFound.GetHashCode()];
        }

        timer.Stop();

        result.notFoundItem = timer.Elapsed.TotalMilliseconds;

        return result;
    }

    private SearchResult FindInArray()
    {
        SearchResult result = new SearchResult();
        result.SeachType = "FindInArray";
        result.itterations = 1;

        Stopwatch timer = new Stopwatch();

        timer.Start();
        foreach (TaskBase t in arrayBoundaryTask)
        {
            if (t.Name == NameOfFirst)
            {
                break;
            }
        }

        timer.Stop();

        result.firstItem = timer.Elapsed.TotalMilliseconds;

        timer.Reset();

        timer.Start();
        foreach (TaskBase t in arrayBoundaryTask)
        {
            if (t.Name == NameOfLast)
            {
                break;
            }
        }
        timer.Stop();

        result.lastItem = timer.Elapsed.TotalMilliseconds;

        timer.Reset();

        timer.Start();
        foreach (TaskBase t in arrayBoundaryTask)
        {
            if (t.Name == NameOfNotFound)
            {
                break;
            }
        }

        timer.Stop();

        result.notFoundItem = timer.Elapsed.TotalMilliseconds;

        return result;
    }

    private SearchResult FindInList()
    {
        SearchResult result = new SearchResult();
        result.SeachType = "FindInList";
        result.itterations = 1;

        Stopwatch timer = new Stopwatch();

        timer.Start();
        TaskBase t = listBoundaryTask.Find(x => x.Name == NameOfFirst);

        if (t!=null)
        {

        }

        timer.Stop();

        result.firstItem = timer.Elapsed.TotalMilliseconds;

        timer.Reset();

        timer.Start();
        t = listBoundaryTask.Find(x => x.Name == NameOfLast);

        if (t != null)
        {

        }
        timer.Stop();

        result.lastItem = timer.Elapsed.TotalMilliseconds;

        timer.Reset();

        timer.Start();
        t = listBoundaryTask.Find(x => x.Name == NameOfNotFound);

        if (t != null)
        {

        }

        timer.Stop();

        result.notFoundItem = timer.Elapsed.TotalMilliseconds;

        return result;
    }

答案 3 :(得分:0)

我不认为您可以应用严格的规则来制定防弹指标。您总是可以想象一个退化的Hashtable案例,由于碰撞,您最终会进行O(n)搜索,但是对于实际数据,这种可能性很小。

一般情况下,如果快速搜索对您的应用程序很重要,那么Hashtable类型的构造始终是您的最佳选择。

(Hashtables有各自的缺点 - 它们不是一个神奇的子弹。维基百科对你可能不想选择Hashtable的案例有很好的解释:link

答案 4 :(得分:-1)

字典搜索总是比线性搜索快。