运行标准:C++11
#include<bits/stdc++.h>
#define BinFile "Binfile.bin"
#define TestFile "TestFile.txt"
using namespace std;
typedef struct node{
char key = '\0';
int Weight = 0;
struct node *Leftnode = nullptr;
struct node *Rightnode = nullptr;
}Treenode;
Treenode *root;
struct cmp1{
bool operator() (const Treenode &a, const Treenode &b) const
{
return a.Weight < b.Weight;
}
};
/*bool operator<(node a, node b)
{
a.Weight < b.Weight;
}*/
void TreenodeTransmit(Treenode *a, Treenode *b)
{
a->key = b->key;
a->Weight = b->Weight;
a->Leftnode = b->Leftnode;
a->Rightnode = b->Rightnode;
}
void BuildHuffmanTree(map<char, int> d)
{
priority_queue<Treenode, vector<Treenode>, cmp1> T;
for(auto it : d)
{
Treenode *temp = nullptr;
temp->key = it.first;
temp->Weight = it.second;
T.push(*temp);
}
if(T.size() == 1)
{
Treenode *temp1 = nullptr;
Treenode *temp2 = nullptr;
Treenode *top = nullptr;
*top = T.top();
TreenodeTransmit(temp2, top);
T.pop();
temp1->key = temp2->key, temp1->Weight = temp2->Weight;
temp1->Leftnode = temp2;
temp1->Rightnode = nullptr;
T.push(*temp1);
}
else{
while(T.size() != 1)
{
Treenode *temp3 = nullptr;
Treenode *temp4 = nullptr;
Treenode *Newnode = nullptr;
Treenode *top = nullptr;
*top = T.top();
TreenodeTransmit(temp3, top);
T.pop();
*top = T.top();
TreenodeTransmit(temp4, top);
T.pop();
Newnode->Weight = temp3->Weight + temp4->Weight;
Newnode->Leftnode = temp3, Newnode->Rightnode = temp4;
T.push(*Newnode);
}
}
Treenode *toproot = nullptr;
*toproot = T.top();
TreenodeTransmit(root, toproot);
}
void Getcode(vector<map<char, string>> *Code, string *tmp, Treenode *root)
{
if(root->Leftnode == nullptr && root->Rightnode == nullptr)
{
map<char, string> t;
t[root->key] = *tmp;
Code->push_back(t);
tmp->erase(tmp->end() - 1);
return;
}
else if(root->Leftnode)
{
*tmp += '0';
Getcode(Code, tmp, root->Leftnode);
}
else if(root->Rightnode)
{
*tmp += '1';
Getcode(Code, tmp, root->Rightnode);
}
if(tmp->length())
tmp->erase(tmp->end() - 1);
}
void CompressFile(vector<map<char, string>> *Code, map<char, int> *CharFreq)
{
fstream infile(TestFile);
char c;
string Stream01;
Stream01.clear();
while(!infile.eof())
{
infile >> c;
for(auto iter : *Code)
if(iter.find(c) != iter.end())
Stream01 += iter[c];
}
infile.close();
fstream outfile;
outfile.open(BinFile, ios::out | ios::binary);
for(auto iter : *CharFreq)
{
outfile << iter.first << "~" << iter.second << " ";
cout << iter.first << "~" << iter.second << " " << endl;;
}
outfile << "@#";
while(Stream01.size() >= 8)
{
bitset<8> bit(Stream01, 0, 8);
Stream01.erase(0,8);
outfile << static_cast<char>(bit.to_ulong());
}
if(!Stream01.empty())
{
bitset<8> bits(Stream01);
outfile << static_cast<char>(bits.to_ulong());
}
outfile.close();
}
int main()
{
char c;
string l;
map<char, int> Char_Freq;
map<char, string> Code;
vector<map<char, string>> CodeT;
fstream Compress;
Compress.open("TestFile.txt", ios::in);
while(!Compress.eof())
{
Compress >> c;
cout << 1;
Char_Freq[c]++;
}
Compress.close();
BuildHuffmanTree(Char_Freq);
l.clear();
Getcode(&CodeT, &l, root);//获得编码集
CompressFile(&CodeT, &Char_Freq);
return 0;
}