确定 vector<char> 中频率最高的 char 元素?
Posted
技术标签:
【中文标题】确定 vector<char> 中频率最高的 char 元素?【英文标题】:Determining most freq char element in a vector<char>? 【发布时间】:2012-08-21 06:22:19 【问题描述】:我正在尝试确定以字符为元素的向量中最常见的字符。
我正在考虑这样做:
循环遍历向量并创建一个映射,其中键是向量中的唯一字符。相应的值将是该字符频率的整数计数。 遍历完向量中的所有元素后,地图将 包含所有字符频率。因此,我将不得不找到 哪个键具有最高值,因此确定最多 向量中的频繁字符。不过,这似乎很令人费解,因此我想知道是否有人可以建议这种方法在性能/良好编码方面是否被认为是“可接受的”
能否以更好的方式做到这一点?
【问题讨论】:
你所描述的绝对是解决这个问题的正常方法。你问的是这个吗? 最大矢量尺寸有多大?向量中允许使用哪些字符? 这里有很多答案:***.com/questions/1991984/… 复杂?这是完成这项任务的最直接明显的方法。它应该是您的首选,如果在 profiling 之后确定效率不够,那么您可以查看其他选项。 @Hbcdev 我不确定这是否是常见的解决方案,因为它似乎是我能想到的最直观的解决方案,但我不确定它是否会被认为在行业中效率低下无法接受.... 【参考方案1】:如果您只使用常规 ascii 字符,您可以使解决方案更快一些 - 使用大小为 256 的数组,而不是使用地图,并计算数组中具有给定代码“x”的字符的出现次数单元格count[x]
。这将从您的解决方案中删除一个对数(256),从而使其更快一些。我认为在优化这个算法方面可以做的不多。
【讨论】:
另外这个解决方案是缓存友好的。 当心:char
可能被签名,在这种情况下,将其用作索引......令人惊讶。【参考方案2】:
对一个字符向量进行排序,然后遍历该向量以查找最大运行长度似乎比使用映射方法快 5 倍(使用下面相当不科学的测试代码作用于 16M 字符)。从表面上看,这两个函数的执行应该彼此接近,因为它们的执行时间为 O(N log N)。但是排序方法可能受益于就地向量排序的branch prediction 和move semantics。
结果输出是:
Most freq char is '\334', appears 66288 times.
usingSort() took 938 milliseconds
Most freq char is '\334', appears 66288 times.
usingMap() took 5124 milliseconds
代码是:
#include <iostream>
#include <map>
#include <vector>
#include <chrono>
void usingMap(std::vector<char> v)
std::map<char, int> m;
for ( auto c : v )
auto it= m.find(c);
if( it != m.end() )
m[c]++;
else
m[c] = 1;
char mostFreq;
int count = 0;
for ( auto mi : m )
if ( mi.second > count )
mostFreq = mi.first;
count = mi.second;
std::cout << "Most freq char is '" << mostFreq << "', appears " << count << " times.\n";
void usingSort(std::vector<char> v)
std::sort( v.begin(), v.end() );
char currentChar = v[0];
char mostChar = v[0];
int currentCount = 0;
int mostCount = 0;
for ( auto c : v )
if ( c == currentChar )
currentCount++;
else
if ( currentCount > mostCount)
mostChar = currentChar;
mostCount = currentCount;
currentChar = c;
currentCount = 1;
std::cout << "Most freq char is '" << mostChar << "', appears " << mostCount << " times.\n";
int main(int argc, const char * argv[])
size_t size = 1024*1024*16;
std::vector<char> v(size);
for ( int i = 0; i < size; i++)
v[i] = random() % 256;
auto t1 = std::chrono::high_resolution_clock::now();
usingSort(v);
auto t2 = std::chrono::high_resolution_clock::now();
std::cout
<< "usingSort() took "
<< std::chrono::duration_cast<std::chrono::milliseconds>(t2-t1).count()
<< " milliseconds\n";
auto t3 = std::chrono::high_resolution_clock::now();
usingMap(v);
auto t4 = std::chrono::high_resolution_clock::now();
std::cout
<< "usingMap() took "
<< std::chrono::duration_cast<std::chrono::milliseconds>(t4-t3).count()
<< " milliseconds\n";
return 0;
【讨论】:
我的猜测是排序方法受益于更少的堆分配和更好的缓存局部性。 @Phillip Ngan,“:”是什么运算符? 无论如何,我有一个类似的问题。如果您看一下将不胜感激:***.com/questions/21693841/…以上是关于确定 vector<char> 中频率最高的 char 元素?的主要内容,如果未能解决你的问题,请参考以下文章
以行和列的形式访问 vector<vector<char> > 元素