最有效的字符计数算法?

时间:2008-10-10 08:43:05

标签: algorithm

假设您想在某些文本中计算字符的出现次数。

我能想到的最快的方法是使用类似unsigned char charcounts[256]的数组,将其初始化为零,然后查看文本输入中的每个字符并执行charcounts[c]++。然后线性搜索charcounts[]使用两个变量来跟踪最低(到目前为止)的char及其计数,当我们找到较低的值时将其替换为新的char / count,直到我们结束。

所以“text”将是t = 2,e = 1,x = 1.

有更快的方法吗?

4 个答案:

答案 0 :(得分:4)

第一部分 - 计数字母频率 要指出的两个问题,假设这里的语言是C或C ++:

  • 您的代码不会处理发生的字母> 255次(如果char恰好被签名,则为127次。)使“charcounts”成为一组整数可能不会对性能产生太大影响。
  • 您的代码不适用于unicode / international字符

第二部分 - 查找频率最低的字母

  • 如果您正在处理短字符串(“text”,“fred”),那么扫描表格中的所有256个条目就是确定速率的步骤。你最好跟踪初始扫描循环中的最低频率字母。
  • 但是,如果您确实要扫描所有256个条目,则可以在达到“一个”值时立即退出循环(如果您的算法的工作方式如此,则为零)

答案 1 :(得分:4)

算法的第一部分是对字符进行计数 - 这只是生成按键排序的键。

如果你知道你只使用字母字符[A-Za-z] *那么你可以通过减少使用的桶数来优化你的算法,但这只是一个小小的调整。

第二部分只是一个稳定的排序 - 有很多方法可以做到这一点 - wikipedia page on sorting提供了一个很好的总结。如果您只对最少出现的字符感兴趣,那么您描述的(“阶段2”)方法可能效率最高。

我能想到的另一种改进方法是,如果你可以在字符范围内均匀地将字母分成固定数量的桶(比如16),然后在每个桶上递归。任何没有字符的桶都可以丢弃,在扫描/分拣阶段节省一些时间。同样,如果一个桶有一个字符,那么它就完成了。当你知道其中有多个不同的字符时,你还要确保只将一个桶分成16个。

使用单词test作为示例(假设有4个桶,只有小写字符:

  1. 生成4个桶(A-G,H-M,N-T,U-Z)
  2. 分词测试:
    • A-G:e,
    • H-L:
    • N-T:tst
    • U型Z:
  3. 递归到其他水桶 - (A-G有一个角色 - 这一定是最少的,所以我们可以停止
  4. 如果不是这种情况(对于“testes”这个词),我们可以看到H-M和U-Z是空的,所以我们只需要检查N-T(它将包含tsts)。
    • 我们创建了4个桶(N-O,P-Q,R-S和T)。
    • 拆分字母
  5. 这种方法的优点是我们不必扫描每个字母。如果字符范围大小相同,那么这两种方法最多都是O(n),其中n是字符串的长度(这是不可避免的,因为我们总是要查看每个字符),尽管构造字符列表我的例子可能会使算法与O(n ^ 2)一样糟糕。但是随着字符范围的增加,特别是对于短字符串,使用子存储桶将大大提高性能。对于unicode字符串,您可以使用混合方法 - 例如,在第一阶段中分离所有非ascii字符,并使用更简单的方法用于ascii部分。

答案 2 :(得分:1)

你在这里描述了两个任务。第一种是计算流中每个ASCII字符出现的次数,第二种是尝试查找最低频率的字符。

第一个算法看起来非常有效。我无法想到更快的方式。

但是,我不太确定你的第二个算法。您没有明确说明为什么要查找频率最低的字符或输入数据是什么,但我可以想象很容易有多个频率计数为零的字符,那么您希望如何区分它们?

答案 3 :(得分:0)

这听起来像是你所描述的最有效的方法之一。我不确定你想要对第二部分做什么,听起来你想找到排序数据中出现次数最少的字符?