###### 优先队列示例: 哈夫曼编码

//  优先队列示例: 哈夫曼编码

//  Modified By Veiz

//  Huffman.h

#ifndef HUFFMAN_H_
#define HUFFMAN_H_

#include <queue>
#include <vector>
#include <string>
#include <istream>
#include <ostream>
#include <fstream>
#include <iostream>

using namespace std;

struct huffmanNode;
typedef huffmanNode* nodePtr;
struct huffmanNode
{   //霍夫曼树结点
unsigned int freq;   //频率

string code;  //编码
nodePtr left;
nodePtr right;
nodePtr parent;
};

class Compare
{   //比较类
public:
bool operator() (const nodePtr& c1, const nodePtr& c2) const
{
return  ((*c1).freq > (*c2).freq);
}
};

class Huffman
{
private:
static const int MAX_SIZE = 256;
nodePtr nodePtrArray[MAX_SIZE];
priority_queue<nodePtr, vector<nodePtr>, Compare> priorityQueue;  //一个优先队列，函数Compare指定了优先准则
fstream inFile;
string inFilename;
string outFilename;
void CreatePriorityQueue();
void CreateNodePtrArray();
void CreateHuffmanTree();
void CalculateHuffmanCodes();
void SaveToFile();
public:
void CreateHuffmanCodes(string inFilename, string outFilename);
};

#endif /* HUFFMAN_H_ */

//  Huffman.cpp

#include "Huffman.h"

void Huffman::CreatePriorityQueue()

for(int i = 0; i < MAX_SIZE; ++i)
{
nodePtrArray[i] = new huffmanNode;
nodePtrArray[i]->freq = 0;
}

CreateNodePtrArray();

nodePtr entry;
for(int i = 0; i < MAX_SIZE; ++i)
{
entry = nodePtrArray[i];
if(entry->freq > 0)
{
priorityQueue.push(entry);
}
}
}

void Huffman::CreateNodePtrArray()
{
nodePtr entry;
inFile.seekg(0, ios::end);
unsigned int posEnd = inFile.tellg();
inFile.seekg(0, ios::beg);
char ch[1];
for(unsigned int i = 0 ; i < posEnd; ++i)
{
entry = nodePtrArray[(unsigned char)(ch[0])];
++entry->freq;
if(entry->freq == 1)
{   //字符第一次出现
entry->left = 0;
entry->right = 0;
entry->parent = 0;
}
}
}

void Huffman::CreateHuffmanTree()
{
nodePtr left;
nodePtr right;
nodePtr sum;

while(priorityQueue.size() > 1)
{
left = priorityQueue.top(); //从优先队列中取出一个子树
priorityQueue.pop();    //从优先队列中移除一个子树
left->code = string("0");   //左子树用0表示

right = priorityQueue.top();    //从优先队列中取出一个子树
priorityQueue.pop();    //从优先队列中移除一个子树
right->code = string("1");   //右子树用1表示

sum = new huffmanNode;
sum->parent = 0;
sum->freq = left->freq + right->freq;   //子树根的节点标记等于它两个后代的频率计数之和
sum->left = left;
sum->right = right;
left->parent = sum;
right->parent = sum;
priorityQueue.push(sum);    //把新子树置入优先队列
}
}

void Huffman::CalculateHuffmanCodes()
{
string code;
nodePtr entry;

for(int i = 0; i < MAX_SIZE; ++i)
{
code = "";
entry = nodePtrArray[i];
if(entry->freq > 0)
{
do
{
code = entry->code + code;
entry = entry->parent;
}while(entry->parent != 0);
nodePtrArray[i]->code = code;
}
}
}

void Huffman::SaveToFile()
{
nodePtr entry;
string line;
inFile.close();
ifstream inFile;
inFile.open(inFilename.c_str(), ios::in | ios::binary);
ofstream outFile;
outFile.open(outFilename.c_str(), ios::out | ios::binary);
if(!outFile)
{
cerr << "OutputFileNotFoundException";
}
inFile.seekg(0, ios::end);
unsigned int posEnd = inFile.tellg();
inFile.seekg(0, ios::beg);
char ch[1];
for(unsigned int i = 0 ; i < posEnd; ++i)
{
entry = nodePtrArray[(unsigned char)(ch[0])];
outFile.write(entry->code.c_str(), (streamsize)entry->code.length());
}
outFile.close();
}

void Huffman::CreateHuffmanCodes(string inFilename, string outFilename)
{
this->inFilename = inFilename;
inFile.open(inFilename.c_str(), ios::in | ios::binary);
if(!inFile)
{
cerr << "InputFileNotFoundException";
}
this->outFilename = outFilename;

CreatePriorityQueue();
CreateHuffmanTree();
CalculateHuffmanCodes();
SaveToFile();
}

//  main.cpp

#include <string>
#include <iostream>
#include "Huffman.h"
using namespace std;

int main(int argc, char* argv[])
{
const string USAGE_MESSAGE = "Usage: HUFFMAN [[drive:][path]inputfilename] [[drive:][path]outputfilename]";
const string CONTINUE_MESSAGE = "Press any key to continue...";
if(argc != 3)
{
cout << USAGE_MESSAGE << endl;
}
else
{
string inputFilename(argv[1]);
string outputFilename(argv[2]);
Huffman huffman;
huffman.CreateHuffmanCodes(inputFilename, outputFilename);
}
cout << CONTINUE_MESSAGE << endl;
cin.get();
return 0;
}

#### C++优先队列解决哈夫曼(Huffmam)编码问题 (STL priority_queue)

2017-05-27 20:39:30

#### 优先队列实现 哈夫曼编码

2017-05-19 16:43:03

#### 哈夫曼编码问题再续（下篇）——优先队列求解

2016-03-30 22:21:20

#### 哈夫曼编码，元素为指针的优先队列

2016-08-23 04:25:33

#### 优先队列实现哈夫曼编码（贪心法）

2017-09-10 12:16:59

#### 优先队列的STL运用与哈夫曼树的实现

2017-10-31 20:12:54

#### 哈夫曼树--九度 1172 & 1107 [优先队列实现小顶堆]

2017-02-25 09:38:58

#### c++使用优先队列来构建huffman树[哈夫曼树]

2011-12-18 17:28:28

#### 九、堆和优先队列---(5)优先队列解决哈夫曼编码

2016-04-29 14:57:32

#### hdu 2527 Safe Or Unsafe（优先队列+哈夫曼树）

2013-07-09 19:51:47