C++ 如何读取二进制文件来计算哈夫曼树的频率?
作为唯一的参数,我必须从“二进制文件”计算哈夫曼树的频率。我怀疑二进制文件是只包含“0”和“1”的文件 而频率是字母数量的重复(例如,这里的abbacdd freq为a=2,b=2,c=1,d=2)。 我的结构必须是这样的: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
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()(仅限内置函数)执行此操作。