【问题标题】:Count occurrences of each letter in a file?计算文件中每个字母的出现次数?
【发布时间】:2013-01-03 18:15:00
【问题描述】:

即使文件大小为 4GB 或更大,如何以优化的方式找到字母 A-Z 的出现(忽略大小写)? C++/C 中可能有哪些不同的实现?

一个实现是:

伪代码

A[26]={0}
loop through each character ch in file
If isalpha(ch)
     A[tolower(ch)-'A']+ = 1
End If
end loop

【问题讨论】:

  • 如果你操作的是4GB的文件,那么这个程序的运行时间将会被磁盘I/O支配。优化计数将毫无意义。您需要优化 I/O 部分。
  • 根据您的应用程序和周围的东西,它可能是一个选项,可以将已经计算的统计数据缓存在磁盘上/在数据库中及其修改时间。只是给出一个想法......
  • 对不起,伙计。但是对于这样的问题,您必须考虑使用 apache hadoop 和 map reduce。顺便说一句,他们引入的第一个基本问题与您的重复。
  • @SRINI794,您的磁盘通常没有并行硬件路径。
  • @SRINI794,这就是 Raymond Chen 试图提出的观点——你可以将计数速度提高 1000 倍,但这并没有什么不同,你还在等待磁盘。更多线程实际上会伤害您,因为它们可能会从磁盘的不同部分读取。

标签: c++ c algorithm file optimization


【解决方案1】:

我认为剩下的优化不多。

  • 不是为每个元素计算 tolower()-'A',而是计算每个字符的出现次数(在 char[256] 累加器中),然后进行区分大小写的计算(可能更有效或不更有效,试试吧) .

  • 一定要使用缓冲输入(fopen,也许用setvbuf分配更大的缓冲区)。

例如:

acum[256]={0}
loop through each character 'c' in file
     acum[c]++
end loop
group counts corresponding to same lowercase/uppercase letters

另外,请记住,这假定为 ASCII 或派生(一个八位字节 = 一个字符)编码。

【讨论】:

  • 必须小心 256 的数组,因为一半的字符值将是负数。 A[c+128]++
  • @MarkRansom:如果使用 getcch 是 int,则不会。
  • @leonbloy,有趣的问题。我一直使用freadread 一次得到一堆,所以我不太了解getc 的行为。
  • 也许内存映射文件可能有一些好处,但除此之外,这与不分块文件一样好。
【解决方案2】:

对于 4GB,这不会是瞬时的。我知道如何更快地完成您正在做的事情。

此外,您的代码不会处理制表符、空格或其他字符。您需要使用isalpha(),并且只有在返回 true 时才增加计数。

请注意,isalpha() 非常快。但是,同样,如果输入非常大,这段代码不会是即时的。

TCHAR a[26] = { 0 };

for (int i = 0; i < length; i++)
{
    if (isalpha(text[i]))
    {
        a[tolower(text[i]) - 'a']++;
    }
}

【讨论】:

  • 是的,我知道我的执行速度很慢!!我只是想知道是否有更快的方法来实现这个?
  • 我想我已经回答了,除了显示你的代码缺少的东西。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-23
  • 1970-01-01
  • 2016-05-22
  • 2020-07-23
  • 1970-01-01
  • 2017-10-13
  • 2013-09-08
相关资源
最近更新 更多