如何改进此字符计数算法
How to improve this character count algorithm
我想构造一个函数,该函数执行文件分析,从0x0到0xff的每个字节计数及其频率在数组中返回
。所以,我写了这个原型:
// function prototype and other stuff
unsigned int counts[256] = {0}; // byte lookup table
FILE * pFile; // file handle
long fsize; // to store file size
unsigned char* buff; // buffer
unsigned char* pbuf; // later, mark buffer start
unsigned char* ebuf; // later, mark buffer end
if ( ( pFile = fopen ( FNAME , "rb" ) ) == NULL )
{
printf("Error");
return -1;
}
else
{
//get file size
fseek (pFile , 0 , SEEK_END);
fsize = ftell (pFile);
rewind (pFile);
// allocate space ( file size + 1 )
// I want file contents as string for populating it
// with pointers
buff = (unsigned char*)malloc( sizeof(char) * fsize + 1 );
// read whole file into memory
fread(buff,1,fsize,pFile);
// close file
fclose(pFile);
// mark end of buffer as string
buff[fsize] = ' ';
// set the pointers to beginning and end
pbuf = &buff[0];
ebuf = &buff[fsize];
// Here the Bottleneck
// iterate entire file byte by byte
// counting bytes
while ( pbuf != ebuf)
{
printf("%cn",*pbuf);
// update byte count
counts[(*pbuf)]++;
++pbuf;
}
// free allocated memory
free(buff);
buff = NULL;
}
// printing stuff
但这种方式较慢。我正在寻找相关的算法,因为我已经看过 HxD 例如做得更快。
我认为也许一次读取一些字节可能是一种解决方案,但我不知道如何。
我需要帮助或建议。
谢谢。
假设你的文件不是太大,它会导致系统开始分页,因为你正在将整个东西读入内存,你的算法与通用数据一样好 - O(n)
。
你需要删除printf
(如上所述(;但除此之外,如果性能不高于提高它的唯一方法,那就是查看生成的汇编程序 - 可能编译器没有优化所有的取消引用(GCC应该这样做(。
如果您碰巧对数据集有所了解,那么可能会有改进 - 如果它是一个位图类型的图像,可能具有相同的字节块,那么可能值得做一点运行长度编码。也可能有一些数据集实际上值得首先对数据进行排序(尽管这将一般情况减少到O(nlog(n))
,所以不太可能。
RLE 看起来像(未经测试,可能是我头顶上的次优免责声明(
unsigned int cur_count=1;
unsigned char cbuf=*(++pbuf);
while ( pbuf != ebuf)
{
while( pbuf != ebuf && cbuf == *pbuf )
{
cur_count++;
pbuf++;
}
counts[cbuf]+=cur_count;
cur_count=0;
}
counts[cbuf]+=cur_count;
您通常可以通过增加程序大小来换取速度的提高,我认为这在您的情况下可以很好地工作。我会考虑用无符号的短*指针替换您的无符号字符*指针,并一次有效地处理两个字节。这样,您就有一半的数组索引增量、一半的偏移量计算到累加器中、一半的累加数量和一半的测试数量来查看循环是否已完成。
就像我说的,这将以增加程序大小为代价,所以你的累加器阵列现在需要 65536 个元素而不是 256 个,但这是一个很小的代价。我承认在易读性方面也存在权衡。
最后,您必须对我新的、更大的累加器的所有 65536 个元素运行索引,并用 0xff 屏蔽它以获得第一个字节并移位 8 位以获得第二个字节。然后,您将拥有与原始累加器对应的两个索引,您可以从那里将 2 个累加器累加到原始 256 累加器中。
附言请注意,虽然您一次可以处理几乎所有文件 2 个字节,但如果您的文件大小是奇数字节,则必须自行处理最后一个字节。
P.P.S. 请注意,这个问题很容易跨 4 个线程并行化,如果你想让你的备用 3 个 CPU 内核做一些比摆动拇指更有用的事情;-(
- C++字符*缓冲区的大小
- HEX值到wchar_t字符(UTF-8)的转换
- 为什么 Serial.println(<char[]>);返回随机字符?
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 我的字符计数代码计算错误.为什么
- 字符串-C++后显示的随机字符
- 将Integer转换为4字节的unsined字符矢量(按大端字节顺序)
- 如何在C++中从字符串中分割字符
- 为什么msgrcv()将垃圾字符馈送到缓冲区
- 基于ELO的团队匹配算法
- 给定字符的排列算法,具有条件C++的重复
- 使用字符** argv 时如何避免指针算法
- 我无法获得基于读取字符数组的算法来工作
- 是否有一种算法可以查找字符串中任何指定字符的第一次出现
- RSA数字和字符值算法
- 如何改进此字符计数算法
- XOR加密算法无法处理长度超过127个字符的输入
- 实现O(n)算法来确定字符串是否所有字符都是唯一的
- 为重复字符打印星号的算法
- C中相同字符子串的递归算法