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

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

//  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)
    {       
        inFile.read(ch, 1);
        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)
    {       
        inFile.read(ch, 1);
        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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值