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

时间:2014-02-26 15:05:58

标签: c++ c data-structures binaryfiles huffman-code

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

而频率是字母数量的重复(例如,abbacdd这里的频率为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 */
};

但我完全不明白如何从“。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  ..... 

所以,我根本不了解频率在哪里以及符号在哪里。如何存储符号以及如何计算频率。实际上,在有频率和符号之后,我将使用它来创建HUffman树。

2 个答案:

答案 0 :(得分:2)

首先,您需要创建某种频率表 您可以使用std::map 你会做这样的事情:

#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> ()) ;

您仍然需要创建一个频率表。

答案 1 :(得分:1)

霍夫曼树中的符号可以是任何东西,
但是你必须使用每个符号unsigned char的身份 你应该拿一个字节? 所以不,不仅是0或1,而是八次0或1。

就像输出xxd中某处的00010011一样 xxd -b每个字节只会给你八个0/1 你也可以写一个0到255之间的数字,
0123456789abcdef 的两个字符 有很多可能性如何在屏幕上显示一个字节,
但这根本不重要。

如果您知道如何阅读C / C ++中的文件内容,请执行 只需阅读unsigned char,直到文件结束为止 并计算那里的值是多少。就这样。

由于您可能在程序代码中写入十进制数字,所以 有256个不同的值(0,1,2 ... 255) 所以你需要256个整数(在一个数组中,或你的Node结构......) 计算每个值出现的频率。