Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.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++ 如何改进这个字符计数算法_C++_C_Algorithm - Fatal编程技术网

C++ 如何改进这个字符计数算法

C++ 如何改进这个字符计数算法,c++,c,algorithm,C++,C,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 unsign

我想构造一个函数,执行一个文件分析,在数组中返回从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] = '\0';

    // 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("%c\n",*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看起来有点像(未经测试,可能是我头脑中的次优免责声明)


你可以经常把程序大小增加来提高速度,我认为在你的情况下可以很好地工作。我会考虑用未签名的短指针替换你的无符号char指针,并且一次有效地处理两个字节。这样,数组索引增量的一半,CALUCL的一半。向累加器中输入偏移量的一半,累加次数的一半,以及查看循环是否完成的测试次数的一半

正如我所说,这将以增加程序大小为代价,因此您的累加器数组现在需要65536个元素,而不是256个元素,但这是一个很小的代价。我承认在易读性方面也有一个折衷

最后,您必须对我新的更大累加器的所有65536个元素运行一个索引,并用0xff屏蔽它以获得第一个字节,并将其移位8位以获得第二个字节。然后,您将拥有与原始累加器相对应的两个索引,您可以从那里将2个累加到原始256累加器中

请注意,尽管您一次可以处理几乎所有的文件2个字节,但如果您的文件大小是奇数字节,则必须自行处理最后一个字节


p.p.S.请注意,如果您想让备用的3个CPU内核做一些比摆弄它们的拇指更有用的事情,那么这个问题很容易在4个线程之间并行处理;-)

如果您不打印每个字符,速度会快得多。I/O非常慢。您需要触摸文件中的每个字节,使其更快的是以块的形式读取它(正如您所做的),因此它是一个很好的实现(对于
C
)。有一件事让我很恼火,那就是你一次缓冲了整个文件,这对大文件来说是个坏主意。。您应该逐块读取它(每个块的大小应为2:10242048,…)。并从循环中删除
printf
。您可能应该
printf
每个字符。;-)没有理由认为缓冲区必须是文件的大小。让它有一些适合寻呼机的尺寸,比如8KiB。此外,如果不将每个字符打印到标准输出,处理速度会快得多。试着分析一下时间的走向。这个问题更适合你
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;