Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.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_Data Structures_Binaryfiles_Huffman Code - Fatal编程技术网

C++ 如何读取二进制文件来计算哈夫曼树的频率?

C++ 如何读取二进制文件来计算哈夫曼树的频率?,c++,c,data-structures,binaryfiles,huffman-code,C++,C,Data Structures,Binaryfiles,Huffman Code,作为唯一的参数,我必须从“二进制文件”计算哈夫曼树的频率。我怀疑二进制文件是只包含“0”和“1”的文件 而频率是字母数量的重复(例如,这里的abbacdd freq为a=2,b=2,c=1,d=2)。 我的结构必须是这样的: struct Node { unsigned char symbol; /* the symbol or alphabets */ int freq; /* related frequency */ struct Node *left,*ri

作为唯一的参数,我必须从“二进制文件”计算哈夫曼树的频率。我怀疑二进制文件是只包含“0”和“1”的文件

而频率是字母数量的重复(例如,这里的abbacdd freq为a=2,b=2,c=1,d=2)。 我的结构必须是这样的:

struct Node
{
unsigned char symbol;   /* the symbol or alphabets */
int freq;               /* related frequency */
struct Node *left,*right; /* Left and right leafs */
};
#include <algorithm>
#include <fstream>
#include <map>
#include <string>

std::map <unsigned char, int> CreateFrequencyTable (const std::string &strFile)
{
    std::map <unsigned char, int> char_freqs ; // character frequencies

    std::ifstream file (strFile) ;

    int next = 0 ;
    while ((next = file.get ()) != EOF) {
        unsigned char uc = static_cast <unsigned char> (next) ;

        std::map <unsigned char, int>::iterator iter ;
        iter = char_freqs.find (uc) ;

        // This character is in our map.
        if (iter != char_freqs.end ()) {
            iter->second += 1 ;
        }

        // This character is not in our map yet.
        else {
            char_freqs [uc] = 1 ;
        }
    }

    return char_freqs ;
}
std::map <unsigned char, int> char_freqs = CreateFrequencyTable ("file") ;
std::map <unsigned char, int>::iterator iter = std::max_element (
    char_freqs.begin (), 
    char_freqs.end (), 
    std::map <unsigned char, int>::value_comp
) ;
// Make sure to #include <iterator>
std::ifstream file ("test.txt") ;
std::istream_iterator <unsigned char> begin = file ;
std::vector<unsigned char> vecBuffer (begin, std::istream_iterator <unsigned char> ()) ;
但我完全不明白如何从“.bin”文件(只包含“0”和“1”)中获取符号和

当我尝试查看文件的内容时,我得到:

hp@ubuntu:~/Desktop/Internship_Xav/Huf_pointer$ xxd -b out.bin 
0000000: 00000000 00000000 00000000 00000000 00000000 00000000  ......
0000006: 00000000 00000000 00000000 00000000 00000000 00000000  ......
000000c: 00000000 00000000 00000000 00000000 00000000 00000000  ......
0000012: 00000000 00000000 00000000 00000000 00000000 00000000  ......
0000018: 00000000 00000000 00000000 00000000 00000000 00000000  ......
000001e: 00000000 00000000 00000000 00000000 00000000 00000000  ......
0000024: 00000000 00000000 00000000 00000000 00000000 00000000  ......
000002a: 00000000 00000000 00000000 00000000 00000000 00000000  ......
0000030: 00000000 00000000 00000000 00000000 00000000 00000000  ......
.........//Here also there is similar kind of data    ................
00008ca: 00010011 00010011 00010011 00010011 00010011 00010011  ......
00008d0: 00010011 00010011 00010011 00010011 00010011 00010011  ......
00008d6: 00010011 00010011 00010011 00010011 00010011 00010011  ..... 

所以,我根本不明白频率在哪里,符号在哪里。如何存储符号以及如何计算频率。事实上,在获得频率和符号后,我将使用它创建哈夫曼树。

哈夫曼树中的符号可以是任何东西,
但由于每个符号都必须使用
无符号字符

您可能需要一个字节?
所以不,不只是0或1,而是8次0或1

比如在输出的
xxd

xxd-b
每字节只会给您八个0/1。
您也可以写一个介于0和255之间的数字,
或者是0123456789abcdef的一个字符的两倍
如何在屏幕上显示字节有很多可能性,
但这一点都不重要

如果您知道如何用C/C++读取文件内容,
只需读取
无符号字符
,直到文件结束
然后计算哪个值是多久出现一次。就这些

由于您可能正在程序代码中编写十进制数,
有256个不同的值(0,1,2…255)。
因此,您需要256个整数(在数组中,或在节点结构中…)

要计算每个值出现的频率。

首先,需要创建某种频率表。
您可以使用一个。
您可以这样做:

struct Node
{
unsigned char symbol;   /* the symbol or alphabets */
int freq;               /* related frequency */
struct Node *left,*right; /* Left and right leafs */
};
#include <algorithm>
#include <fstream>
#include <map>
#include <string>

std::map <unsigned char, int> CreateFrequencyTable (const std::string &strFile)
{
    std::map <unsigned char, int> char_freqs ; // character frequencies

    std::ifstream file (strFile) ;

    int next = 0 ;
    while ((next = file.get ()) != EOF) {
        unsigned char uc = static_cast <unsigned char> (next) ;

        std::map <unsigned char, int>::iterator iter ;
        iter = char_freqs.find (uc) ;

        // This character is in our map.
        if (iter != char_freqs.end ()) {
            iter->second += 1 ;
        }

        // This character is not in our map yet.
        else {
            char_freqs [uc] = 1 ;
        }
    }

    return char_freqs ;
}
std::map <unsigned char, int> char_freqs = CreateFrequencyTable ("file") ;
std::map <unsigned char, int>::iterator iter = std::max_element (
    char_freqs.begin (), 
    char_freqs.end (), 
    std::map <unsigned char, int>::value_comp
) ;
// Make sure to #include <iterator>
std::ifstream file ("test.txt") ;
std::istream_iterator <unsigned char> begin = file ;
std::vector<unsigned char> vecBuffer (begin, std::istream_iterator <unsigned char> ()) ;
#包括
#包括
#包括
#包括
标准::映射CreateFrequencyTable(常量标准::字符串和标准文件)
{
std::map char\u freqs;//字符频率
std::ifstream文件(strFile);
int next=0;
而((next=file.get())!=EOF){
无符号字符uc=静态_转换(下一步);
std::map::迭代器iter;
iter=字符频率查找(uc);
//这个角色在我们的地图上。
if(iter!=char\u freqs.end()){
iter->second+=1;
}
//这个角色还不在我们的地图上。
否则{
字符频率[uc]=1;
}
}
返回字符频率;
}
然后你可以像这样使用这个函数:

struct Node
{
unsigned char symbol;   /* the symbol or alphabets */
int freq;               /* related frequency */
struct Node *left,*right; /* Left and right leafs */
};
#include <algorithm>
#include <fstream>
#include <map>
#include <string>

std::map <unsigned char, int> CreateFrequencyTable (const std::string &strFile)
{
    std::map <unsigned char, int> char_freqs ; // character frequencies

    std::ifstream file (strFile) ;

    int next = 0 ;
    while ((next = file.get ()) != EOF) {
        unsigned char uc = static_cast <unsigned char> (next) ;

        std::map <unsigned char, int>::iterator iter ;
        iter = char_freqs.find (uc) ;

        // This character is in our map.
        if (iter != char_freqs.end ()) {
            iter->second += 1 ;
        }

        // This character is not in our map yet.
        else {
            char_freqs [uc] = 1 ;
        }
    }

    return char_freqs ;
}
std::map <unsigned char, int> char_freqs = CreateFrequencyTable ("file") ;
std::map <unsigned char, int>::iterator iter = std::max_element (
    char_freqs.begin (), 
    char_freqs.end (), 
    std::map <unsigned char, int>::value_comp
) ;
// Make sure to #include <iterator>
std::ifstream file ("test.txt") ;
std::istream_iterator <unsigned char> begin = file ;
std::vector<unsigned char> vecBuffer (begin, std::istream_iterator <unsigned char> ()) ;
std::map char_freqs=CreateFrequencyTable(“文件”);
您可以获得频率最高的元素,如下所示:

struct Node
{
unsigned char symbol;   /* the symbol or alphabets */
int freq;               /* related frequency */
struct Node *left,*right; /* Left and right leafs */
};
#include <algorithm>
#include <fstream>
#include <map>
#include <string>

std::map <unsigned char, int> CreateFrequencyTable (const std::string &strFile)
{
    std::map <unsigned char, int> char_freqs ; // character frequencies

    std::ifstream file (strFile) ;

    int next = 0 ;
    while ((next = file.get ()) != EOF) {
        unsigned char uc = static_cast <unsigned char> (next) ;

        std::map <unsigned char, int>::iterator iter ;
        iter = char_freqs.find (uc) ;

        // This character is in our map.
        if (iter != char_freqs.end ()) {
            iter->second += 1 ;
        }

        // This character is not in our map yet.
        else {
            char_freqs [uc] = 1 ;
        }
    }

    return char_freqs ;
}
std::map <unsigned char, int> char_freqs = CreateFrequencyTable ("file") ;
std::map <unsigned char, int>::iterator iter = std::max_element (
    char_freqs.begin (), 
    char_freqs.end (), 
    std::map <unsigned char, int>::value_comp
) ;
// Make sure to #include <iterator>
std::ifstream file ("test.txt") ;
std::istream_iterator <unsigned char> begin = file ;
std::vector<unsigned char> vecBuffer (begin, std::istream_iterator <unsigned char> ()) ;
std::map::iterator iter=std::max\u元素(
char_freqs.begin(),
char_freqs.end(),
标准::映射::值
) ;
然后你需要建立你的哈夫曼树。
请记住,这些字符都是叶节点,因此需要一种方法来区分叶节点和非叶节点

更新

如果从文件中读取单个字符的速度太慢,则始终可以将所有内容加载到向量中,如下所示:

struct Node
{
unsigned char symbol;   /* the symbol or alphabets */
int freq;               /* related frequency */
struct Node *left,*right; /* Left and right leafs */
};
#include <algorithm>
#include <fstream>
#include <map>
#include <string>

std::map <unsigned char, int> CreateFrequencyTable (const std::string &strFile)
{
    std::map <unsigned char, int> char_freqs ; // character frequencies

    std::ifstream file (strFile) ;

    int next = 0 ;
    while ((next = file.get ()) != EOF) {
        unsigned char uc = static_cast <unsigned char> (next) ;

        std::map <unsigned char, int>::iterator iter ;
        iter = char_freqs.find (uc) ;

        // This character is in our map.
        if (iter != char_freqs.end ()) {
            iter->second += 1 ;
        }

        // This character is not in our map yet.
        else {
            char_freqs [uc] = 1 ;
        }
    }

    return char_freqs ;
}
std::map <unsigned char, int> char_freqs = CreateFrequencyTable ("file") ;
std::map <unsigned char, int>::iterator iter = std::max_element (
    char_freqs.begin (), 
    char_freqs.end (), 
    std::map <unsigned char, int>::value_comp
) ;
// Make sure to #include <iterator>
std::ifstream file ("test.txt") ;
std::istream_iterator <unsigned char> begin = file ;
std::vector<unsigned char> vecBuffer (begin, std::istream_iterator <unsigned char> ()) ;
//确保#包括
std::ifstream文件(“test.txt”);
std::istream\u迭代器begin=file;
std::vectorvecbuffer(begin,std::istream_迭代器());

您仍然需要创建频率表。

“我怀疑二进制文件是否仅包含“0”和“1”的文件。哦,相信我,这就是它们包含的内容。符号可能就是您看到的数据。您很可能需要自己计算频率。@jliv902抱歉,请您详细解释一下好吗?假设我取“0000030:00000000 00000000 00000000 00000000 00000000…”,那么符号是什么,我如何从中计算频率?你知道我必须从中创建一棵哈夫曼树。你知道我将如何使用这个二进制文件吗?@jliv902对不起,请你详细解释一下?假设我取“00008d0:00010011 00010011 00010011 00010011 00010011 00010011 00010011……”,那么符号是什么?我必须如何从它计算频率?你知道我必须从中创建一个哈夫曼树。你知道我将如何使用这个二进制文件吗?@user234839 00010011将是一个符号,你必须将它存储在数据结构中,并存储你在文件中看到它的次数计数。谢谢,我试着这样做了(counter=1;counter OK谢谢,我会尝试一下,并在它工作后标记为已解决。但是如果有n个符号,那么这个频率计算的复杂性是什么?@user234839我相信创建表将是
O(nlogn)
,获得频率最高的元素将是
O(logn)
。从理论上讲,这比使用数组或向量要好,但由于缓存空间位置的原因,数组或向量的性能可能会更好。无论哪种方式,您的瓶颈都是IO(一次获取一个字符的速度会很慢),而不是容器。如果在分析程序之后,您发现它太慢,您可以始终将整个文件读取到内存中,然后创建此频率表。实际上,我必须使用read()(仅限内置函数)执行此操作。