Huffman编码译码算法的C++实现

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

头文件:

 

/*****************************************************************************
 *                               huffmancode.h
 *
 * Huffman coding algorighm implemented by C++ template.
 *
 * This class is designed for Huffman codeing and decoding algorighm. The
 * priority queue is used in building Huffman tree. For comparing pointers
 * of Huffman Tree Node by their pointing contents, I use the smart pointer
 * replacing nomal pointer. And for saving memory, the coded word is stored
 * bit-by-bit in an unsigned char array.
 *
 * Zhang Ming, 20010-07, Xi'an Jiaotong University.
 *****************************************************************************/


#ifndef HUFFMANCODE_H
#define HUFFMANCODE_H


#include 
#include 


using namespace std;


namespace itlab
{

    /**
     * Object node to be coded
     */
    template 
    struct CodeObject
    {
        Object data;
        Weight cost;
    };
    // struct CodeObject


    /**
     * Huffman codeword node
     */
    const int CODESIZE = 2;
    template 
    struct HCNode
    {
        Object data;
        unsigned char bits[CODESIZE];
        unsigned int length;
    };
    // struct HCNode


    /**
     * Huffman tree node
     */
    template 
    struct HTNode
    {
        Object data;
        Weight cost;
        HTNode *left,
                              *right;

        HTNode() : data(Object()), cost(Weight(0)), left(NULL), right(NULL)
        { }
        HTNode( const Object &x, const Weight w,
                HTNode *lp=NULL, HTNode *rp=NULL )
        {   data = x; cost = w; left = lp; right = rp;    }

        operator Weight() const
        {   return cost;    }

    };
    // struct HTNode


    /**
     * Smart pointer for Huffman tree bode
     */
    template 
    class HTNSmartPtr
    {

    public:

        HTNSmartPtr( HTNode *p = NULL )
        {   ptr = p;    }

        HTNode operator*()
        {   return *ptr;    }
        HTNode* operator->()
        {   return ptr;    }

        operator HTNode *()
        {   return ptr;    }
        bool operator<( HTNSmartPtr p )
        {   return ptr->cost < p->cost;    }
        bool operator>( HTNSmartPtr p )
        {   return ptr->cost > p->cost;    }

    private:

        HTNode *ptr;

    };
    // class HTNSmartPtr


    /**
     * Huffman tree
     */
    template 
    class HuffmanTree
    {

    public:

        HuffmanTree();
        ~HuffmanTree();

//        HuffmanTree( const HuffmanTree &rhs );
//        HuffmanTree & operator=( const HuffmanTree &rhs );

        void code( CodeObject *codeArray, int length );
        bool decode( unsigned char bits[CODESIZE], unsigned int length, Object &decodeword );
        void printCode( unsigned char bits[CODESIZE], unsigned int length );
        void printCodeTable();

    private:

        HTNSmartPtr root;
        int arraySize;
        HCNode *codeTable;

        void createHuffmanTree( CodeObject *codeArray );
        void createCodeTable();
        void createCodeTableRecursive( HTNSmartPtr ht,
                                       unsigned char *code, int pos, int &index );

        void setBit( unsigned char *bits, unsigned int pos, unsigned int state );
        unsigned int getBit( unsigned char *codeword, unsigned int pos );

        void destroy( HTNode *&r );

    };
    // class HuffmanTree


    #include "huffmancode-impl.h"

}
// namespace itlab


#endif
// HUFFMANCODE_H 
   

 

实现文件:

 

/*****************************************************************************
 *                             huffmancode-impl.h
 *
 * Implementation for Huffman code.
 *
 * Zhang Ming, 2010-07
 *****************************************************************************/


/**
 * constructors and destructor
 */
template 
HuffmanTree::HuffmanTree() : root(NULL)
{
    arraySize = 0;
    codeTable = NULL;
}

template 
HuffmanTree::~HuffmanTree()
{
    HTNode *r = root;
    destroy(r);
    root = NULL;
    delete []codeTable;
}


/**
 * Huffman codeing.
 */
template 
void HuffmanTree::code( CodeObject *codeArray, int length )
{
    arraySize = length;

    if( codeTable != NULL )
        delete []codeTable;
    codeTable = new HCNode[arraySize];

    createHuffmanTree( codeArray );
    createCodeTable();
}


/**
 * If decodeing successful return ture, else return false;
 */
template 
bool HuffmanTree::decode( unsigned char codeword[CODESIZE], unsigned int length,
                                         Object &decodeword )
{
    unsigned int pos = 0;
    HTNSmartPtr p = root;
    for( pos=0; posleft;
            else
                p = p->right;
        }
        else
            break;

    if( pos == length && p != NULL && p->left == NULL && p->right == NULL  )
    {
        decodeword = p->data;
        return true;
    }

    else
        return false;
}


/**
 * Print the codedword.
 */
template 
inline void HuffmanTree::printCode( unsigned char codewrod[CODESIZE], unsigned int length )
{
    for( unsigned int j=0; j
void HuffmanTree::printCodeTable()
{
	cout << "Object\tCode\tSize" << endl;
	for( int i=0; i
void HuffmanTree::createHuffmanTree( CodeObject *codeArray )
{
    BinaryHeap > heap( arraySize );
    HTNSmartPtr  tree = NULL,
                                subtreeL = NULL,
                                subtreeR = NULL;

    for( int i=0; i( codeArray[i].data, codeArray[i].cost, NULL, NULL );
        heap.insert( tree );
    }

    while( heap.size() > 1 )
    {
        heap.deleteMin( subtreeL );
        heap.deleteMin( subtreeR );
        tree = new HTNode( Object(), subtreeL->cost+subtreeR->cost, subtreeL, subtreeR );
        heap.insert( tree );
    }
    heap.deleteMin( root );
}


/**
 * Create the coded character table.
 */
template 
void HuffmanTree::createCodeTable()
{
    for( int i=0; i
void HuffmanTree::createCodeTableRecursive( HTNSmartPtr ht,
                                                           unsigned char *code, int pos, int &index )
{
    if( ht->left )
    {
        setBit( code, pos, 0 );
        createCodeTableRecursive( ht->left, code, pos+1, index );
    }

    if( ht->right )
    {
        setBit( code, pos, 1 );
        createCodeTableRecursive( ht->right, code, pos+1, index );
    }

    if( ht->left==NULL && ht->right==NULL )
    {
        codeTable[index].data = ht->data;
        for( int i=0; i
void HuffmanTree::setBit( unsigned char *bits, unsigned int pos, unsigned int state )
{
	unsigned char mask = 0x80;
	for( unsigned int i=0; i<(pos % 8); ++i )
		mask = mask >> 1;

	if( state == 1 )
		bits[pos/8] = bits[pos/8] | mask;
	else if( state == 0 )
		bits[pos/8] = bits[pos/8] & (~mask);
    else
        cerr << endl << "The bit to be set should be '1' or '0'!" << endl;

	return;
}


/**
 * Get the state of the bit at position pos in the array bits.
 */
template 
unsigned int HuffmanTree::getBit( unsigned char *bits, unsigned int pos )
{
	unsigned char mask = 0x80;
	for( unsigned int i=0; i<(pos%8); ++i )
		mask = mask >> 1;

	return ( ((mask & bits[(int)(pos/8)]) == mask) ? 1 : 0 );
}


/**
 * Destroy the tree.
 */
template 
void HuffmanTree::destroy( HTNode *&r )
{
    if( r != NULL )
    {
        destroy( r->left );
        destroy( r->right );
        delete r;
    }
    r = NULL;
} 
   

 

测试文件:

 

/*****************************************************************************
 *                              huffmancode_test.cpp
 *
 * Huffman Code class testing.
 *
 * Zhang Ming, 2010-07
 *****************************************************************************/


#include 
#include 
#include "huffmancode.h"


using namespace std;
using namespace itlab;


const int CHARNUM = 128;
template 
void creatCodeInfo( string &str, CodeObject *&codeArr, int &length );
template 
void printCodeInfo( CodeObject *&codeArr, int length );


int main()
{
    int length = 0;
    CodeObject *codeArr = NULL;
    string str = "AAAABBCD";
    creatCodeInfo( str, codeArr, length );
    printCodeInfo( codeArr, length );

    HuffmanTree ht;
    ht.code( codeArr, length );
    ht.printCodeTable();

    char decodedResult;
    unsigned char codeword[CODESIZE];
    cout << "Coding\t" << "Decodedwrod" << endl;
    codeword[0] = 0xC0;
    if( ht.decode( codeword, 3, decodedResult ) )
    {
        ht.printCode( codeword, 3 );
        cout << "\t" << decodedResult << endl;
    }
    else
        cerr << "invalid codeword! " << endl;
    codeword[0] = 0xC0;
    if( ht.decode( codeword, 4, decodedResult ) )
    {
        ht.printCode( codeword, 3 );
        cout << "\t" << decodedResult << endl;
    }
    else
    {
        ht.printCode( codeword, 4 );
        cerr << "\t" << "invalid codeword! " << endl;
    }
    codeword[0] = 0x40;
    if( ht.decode( codeword, 3, decodedResult ) )
    {
        ht.printCode( codeword, 3 );
        cout << "\t" << decodedResult << endl;
    }
    else
    {
        ht.printCode( codeword, 3 );
        cerr << "\t" << "invalid codeword! " << endl;
    }

    cout << endl;
    return 0;
}


/**
 * Generate the array for counting character frequency.
 */
template 
void creatCodeInfo( string &str, CodeObject *&codeArr, int &length )
{
    char charFreq[CHARNUM];
    int index[CHARNUM];
    for( int i=0; i[length];
    for( int i=0; i
void printCodeInfo( CodeObject *&codeArr, int length )
{
    cout << "Object\tCode" << endl;
    for( int i=0; i

 

转载于:https://my.oschina.net/zmjerry/blog/6115

你可能感兴趣的:(Huffman编码译码算法的C++实现)