Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当Dictionary类可用于大文件的字符串计数时,为什么要使用Trie数据结构_C#_.net_Data Structures_Hashtable_Idictionary - Fatal编程技术网

C# 当Dictionary类可用于大文件的字符串计数时,为什么要使用Trie数据结构

C# 当Dictionary类可用于大文件的字符串计数时,为什么要使用Trie数据结构,c#,.net,data-structures,hashtable,idictionary,C#,.net,Data Structures,Hashtable,Idictionary,假设我需要计算一个非常大的文件中的单词(单词被“”分割) 我会做以下事情 不在内存中加载整个文件,逐行读取流 对于每一行,拆分单词并将不同的单词添加到“dictionary”(我的意思是,使用dictionary类) 在.NET中)和他们的计数 现在要检索最常用的单词,请对字典进行排序并获取它 但大多数解决方案都是一种有利于这一点的Trie数据结构,请澄清原因(另外,如果不澄清字典上的哈希表的原因,那就太好了) 谢谢。您可以使用类似于流阅读器的File.ReadLines var mostFre

假设我需要计算一个非常大的文件中的单词(单词被“”分割)

我会做以下事情

  • 不在内存中加载整个文件,逐行读取流
  • 对于每一行,拆分单词并将不同的单词添加到“dictionary”(我的意思是,使用dictionary类) 在.NET中)和他们的计数
  • 现在要检索最常用的单词,请对字典进行排序并获取它


    但大多数解决方案都是一种有利于这一点的Trie数据结构,请澄清原因(另外,如果不澄清字典上的哈希表的原因,那就太好了)


    谢谢。

    您可以使用类似于流阅读器的
    File.ReadLines

    var mostFrequent = File.ReadLines("Path")
        .SelectMany(l => l.Split()) // splits also by tabs
        .GroupBy(word => word)
        .OrderByDescending(g => g.Count())
        .First(); // or Take(10) if you want the top 10
    
    Console.Write("Word:{0} Count:{1}", mostFrequent.Key, mostFrequent.Count());
    

    我忍不住要提到的是,这不仅是一个地图缩减问题,而且是一个复杂的问题

    除此之外,使用trie实现的原因是为了提高查找每个单词以增加其计数的效率(或添加trie中尚不存在的单词)。在基本trie中,每个单词的查找时间是
    O(n)
    ,其中
    n
    是单词中的字符数。在整个文档中,如果没有并行处理,您将只查看
    O(n)
    查找时间,其中
    n
    是文档中的字符数。然后,它(可能)将是一个深度优先搜索来检索所有单词,以便您可以提取所需的信息。深度优先搜索在最坏情况下的性能将是相同的
    O(n)
    ,但由于前缀相同,预期情况会更好

    如果使用不同的结构,例如涉及哈希查找的标准
    System.Collections.Generic.Dictionary
    ,则成本与哈希查找和实现以及哈希冲突的普遍性有关。然而,即使这样,也可能不是成本的主要部分。假设arguendo的散列查找是固定时间的,并且非常简单。因为相等的散列码不能保证字符串相等,所以仍然需要比较字符串是否相等,这几乎可以肯定地实现为
    O(n)
    ,其中
    n
    是字符数(为了简单起见)。因此,根据trie和一些基于散列查找的字典的实现,基于散列查找的字典可能不比trie好,也可能比trie差

    对我的分析的一个有效批评可能是,trie中每个节点的查找时间可能不是常数;它将取决于用于确定后续节点的边的集合。然而,如果我们不关心以后对键进行排序,那么基于哈希查找的字典在这里可能会很好地工作。当输入为一个字符时,哈希冲突不太可能发生,与完整字符串相比,相等比较所涉及的内容要少得多。insert性能也可能是合理的,这同样取决于实现


    但是,如果您知道要按字数确定最前面的
    n
    字数,除了在trie中跟踪它们之外,您可能还需要跟踪最前面的
    n
    字数。这样,在填充trie之后,您不需要重新计算top
    n

    什么确切地说是非常大的意思?“为什么不在dictionary上使用哈希表”:dictionary是一个哈希表;它基本上与Hashtable类相同,只是它是泛型的。你为什么不自己试试呢。当你查询“c#trie类”时,你会从谷歌那里得到很多帮助。当您将它与Linq查询或字典进行比较时,您会发现了解现代计算机工作方式非常非常重要。并且能够提出一个好问题。@ThomasLevesque:“现在要检索最频繁的单词,请对字典进行排序并获取它。”如果他只想查找最频繁的单词+计数,我不明白他为什么需要一本字典。非常大,我指的是一个TB文件或10 TB或更多more@TimSchmelter,我指的是那部分:“但大多数解决方案都是一种有利的Trie数据结构,请澄清原因“不只是一个字,让我们说我想要10个最频繁的words@ThomasLevesque:我想他指的是这样的解决方案:对于这么大的文件,我的方法是不可接受的,但是,我为需要简单方法的人保留它。这也是关于内存消耗的。从trie中非常大的文件中保留单词所需的时间要少得多。在hashmap中,对于单词的每个变体,都会有另一条记录。但在trie中,您将重用现有的word部件。您的“地图减少问题”链接已断开。这一页上的可能是可比的,但我真的不知道,因为我从来没有看过原作@比劳夫斯基:是的,这个链接似乎是等价的,尽管旧的链接还在。我来编辑。