[实例]利用霍夫曼树获得霍夫曼编码并进行加密和解密

 




    奋战一个晚上把基本功能实现了
//HuffmanTree.h

#ifndef HUFFMAN_TREE_H
#define HUFFMAN_TREE_H

#include <Windows.h>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;

namespace HuffmanTreeSpace
{
    struct HuffmanTreeNode
    {
        int nData;
        string strData;
        string strHuffmanCodeing;
        HuffmanTreeNode* pRoot;
        HuffmanTreeNode* pLeftChild;
        HuffmanTreeNode* pRightChild;

        HuffmanTreeNode()
        {
            nData = 0;

            pRoot = NULL;
            pLeftChild = NULL;
            pRightChild = NULL;
        }

//         bool operator < (const HuffmanTreeNode& rhs) const // 升序排序时必须写的函数
//         {
//             return nData < rhs.nData;
//         }
//         bool operator > (const HuffmanTreeNode& rhs) const // 降序排序时必须写的函数
//         {
//             return nData > rhs.nData;
//         }
    };

    typedef struct tag_SingleCode
    {
        int nData;
        string strData;
        string strCoding;
    }SingleCode, *PSingleCode;

    typedef vector<HuffmanTreeNode*> TreeNodeArray;
    typedef vector<SingleCode> HuffmanCodingTable;

    enum  EM_HUFFMAN_ORDER
    {
        EM_HUFFMAN_DLR = 0,
        EM_HUFFMAN_LDR = 1,
        EM_HUFFMAN_LRD = 2
    };

    class HuffmanTree
    {
    public:
        HuffmanTree();

        void AddRawDataToNode(string strData);
        void AddNode(int nData, string strData);
        void MySort();

        void Gnenerate();
        void PrintTreeNode();

        void PrintNode(EM_HUFFMAN_ORDER emType, const HuffmanTreeNode* pNode);
        void GetHuffmanNode(const HuffmanTreeNode* pNode, int nData, string strData);
        string PrintHuffmanCode(int nData, string strData);

        HuffmanTreeNode* GetRoot()
        {
            return m_pRootNode;
        }

        void GenerateCodingTable();
        string HuffmanEncoding(const string& strRaw);
        string HuffmanDecoding(const string& strEncoded);

    public:
        string m_strTemp;
        const HuffmanTreeNode* m_pTemp;

        HuffmanCodingTable m_CodingTable;

    private:
        TreeNodeArray m_TreeNodes; //本示例没有考虑内存的释放,后续可以改进
        HuffmanTreeNode* m_pRootNode;
        string strHuffCode;
    };

    //////////////////////////////////////////////////////////////////////////
    void HuffmanTree_Test1();
    void HuffmanTree_Test2();
    void HuffmanTree_Test3();
}

#endif


#include "HuffmanTree.h"

namespace HuffmanTreeSpace
{
    HuffmanTree::HuffmanTree()
        :m_pRootNode(NULL)
    {
    }

    bool less_second(char char1, char char2)
    {
        return char1 < char2;
    }

    void HuffmanTree::AddRawDataToNode(string strData)
    {
        m_CodingTable.clear();

        //统计字符出现的频率
        string strTemp = strData;
        sort(strTemp.begin(), strTemp.end()/*, less_second*/);

        while (strTemp.size() > 0)
        {
            string strData;
            const char* ptr = strTemp.c_str();
            int nSize = count(strTemp.begin(), strTemp.end(), *ptr);
            strData = *ptr;

            AddNode(nSize, strData);

            strTemp = strTemp.substr(nSize, strTemp.size()-nSize);
        }
    }

    void HuffmanTree::AddNode(int nData, string strData)
    {
        HuffmanTreeNode* pNode = new HuffmanTreeNode();
        pNode->nData = nData;
        pNode->strData = strData;
        m_TreeNodes.push_back(pNode);

        SingleCode singleCode;
        singleCode.nData = nData;
        singleCode.strData = strData;
        m_CodingTable.push_back(singleCode);
    }

    //升序排序
    bool lessmark(const HuffmanTreeNode* treeNode1, const HuffmanTreeNode* treeNode2)
    {
        return (treeNode1->nData < treeNode2->nData);
    }

    //降序排序
    bool greatermark(const HuffmanTreeNode* treeNode1, const HuffmanTreeNode* treeNode2)
    {
        return treeNode1->nData > treeNode2->nData;
    }


    void HuffmanTree::MySort()
    {
        sort(m_TreeNodes.begin(), m_TreeNodes.end(), lessmark);
    }

    void HuffmanTree::Gnenerate()
    {
        MySort();

        while (m_TreeNodes.size() > 1)
        {
            //PrintTreeNode();

            int nsize = m_TreeNodes.size();
            TreeNodeArray::iterator iter = m_TreeNodes.begin();
            TreeNodeArray::iterator iter2 = m_TreeNodes.begin();
            ++iter2;

            HuffmanTreeNode* pNode = new HuffmanTreeNode();

            pNode->nData = (*iter)->nData + (*iter2)->nData;
            pNode->strData = (*iter)->strData + (*iter2)->strData;
            (*iter)->strHuffmanCodeing = "0";
            (*iter2)->strHuffmanCodeing = "1";

            (*iter)->pRoot = pNode;
            (*iter2)->pRoot = pNode;

            pNode->pLeftChild = *iter;
            pNode->pRightChild = *iter2;

            m_TreeNodes.erase(iter2);
            m_TreeNodes.erase(iter);

            m_TreeNodes.push_back(pNode);

            MySort();
        }

        m_pRootNode = *m_TreeNodes.begin();

        GenerateCodingTable();
    }

    void HuffmanTree::PrintTreeNode()
    {
        TreeNodeArray::iterator iter = m_TreeNodes.begin();
        TreeNodeArray::iterator end = m_TreeNodes.end();

        for(; iter != end; ++iter)
        {
            cout << "Val = " << (*iter)->nData << "str = " << (*iter)->strData << " address = "  <<(*iter)->pLeftChild << ", " <<(*iter)->pRightChild << endl;
        }
    }

    void HuffmanTree::PrintNode(EM_HUFFMAN_ORDER emType, const HuffmanTreeNode* pNode)
    {
        if (pNode != NULL)
        {
            if (EM_HUFFMAN_DLR == emType)
            {
                cout << " " << pNode->nData << "(" << pNode->strData << "," << pNode->strHuffmanCodeing << ")";
            }

            //Get Left Leaf
            if (pNode->pLeftChild != NULL)
            {
                PrintNode(emType, pNode->pLeftChild);
            }

            if (EM_HUFFMAN_LDR == emType)
            {
                cout << " " << pNode->nData << "(" << pNode->strData << "," << pNode->strHuffmanCodeing << ")";
            }

            //Get Right Leaf
            if (pNode->pRightChild != NULL)
            {
                PrintNode(emType, pNode->pRightChild);
            }

            if (EM_HUFFMAN_LRD == emType)
            {
                cout << " " << pNode->nData << "(" << pNode->strData << "," << pNode->strHuffmanCodeing << ")";
            }
        }
    }

    void HuffmanTree::GetHuffmanNode(const HuffmanTreeNode* pNode, int nData, string strData)
    {
        if (pNode != NULL)
        {
            if (pNode->nData==nData
             && pNode->strData==strData)
            {
                if (NULL == m_pTemp)
                {
                    m_pTemp = pNode;
                }
                return;
            }
            else
            {
                m_strTemp = m_strTemp.substr(0, m_strTemp.length()-1);
            }

            //Get Left Leaf
            if (pNode->pLeftChild != NULL)
            {
                if (pNode->pLeftChild->nData==nData
                 && pNode->pLeftChild->strData==strData)
                {
                    if (NULL == m_pTemp)
                    {
                        m_pTemp = pNode->pLeftChild;
                    }

                    m_strTemp = m_strTemp.substr(0, m_strTemp.length()-1);
                    return;
                }
                else
                {
                    GetHuffmanNode(pNode->pLeftChild, nData, strData);
                    //cout << "0";
                    //m_strTemp = "0" + m_strTemp;
                }
            }
            else
            {
                m_strTemp = m_strTemp.substr(0, m_strTemp.length()-1);
            }

            //Get Right Leaf
            if (pNode->pRightChild != NULL)
            {
                if (pNode->pRightChild->nData==nData
                    && pNode->pRightChild->strData==strData)
                {
                    if (NULL == m_pTemp)
                    {
                        m_pTemp = pNode->pRightChild;
                    }

                    m_strTemp = m_strTemp.substr(0, m_strTemp.length()-1);
                    return;
                }
                else
                {
                    GetHuffmanNode(pNode->pRightChild, nData, strData);
                    //cout << "1";
                    //m_strTemp = "1" + m_strTemp;
                }
            }
            else
            {
                m_strTemp = m_strTemp.substr(0, m_strTemp.length()-1);
            }
        }
    }

    string HuffmanTree::PrintHuffmanCode(int nData, string strData)
    {
        string strHuffmanCode;

        m_strTemp = "";
        m_pTemp = NULL;

        //cout << "---------------------------------------------------" << endl;
        GetHuffmanNode(m_pRootNode, nData, strData);
        //cout << "Temp=" << m_strTemp  << "\n" << strData << "(" << nData << ") = ";

        const HuffmanTreeNode* ptr = m_pTemp;
        while (ptr != NULL)
        {
            strHuffmanCode = ptr->strHuffmanCodeing + strHuffmanCode;
            //cout << " " << ptr->nData << "(" << ptr->strHuffmanCodeing << ")";
            ptr = ptr->pRoot;
        }
        cout << strData << " = " << strHuffmanCode << endl;
        //cout << "---------------------------------------------------" << endl;

        return strHuffmanCode;
    }

    void HuffmanTree::GenerateCodingTable()
    {
        HuffmanCodingTable::iterator iter= m_CodingTable.begin();
        HuffmanCodingTable::iterator end= m_CodingTable.end();

        for ( ; iter != end; ++iter)
        {
            iter->strCoding = PrintHuffmanCode(iter->nData, iter->strData);
        }
    }

    string& replace_all_distinct(string& str,const   string&   old_value,const   string&   new_value)
    {
        for(string::size_type   pos(0);   pos!=string::npos;   pos+=new_value.length())
        {
            if ((pos=str.find(old_value,pos))!=string::npos)
            {
                str.replace(pos,old_value.length(),new_value);
            }
            else
            {
                break;
            }
        }

        return str;
    }

    string HuffmanTree::HuffmanEncoding(const string& strRaw)
    {
        HuffmanCodingTable::const_iterator iter= m_CodingTable.begin();
        HuffmanCodingTable::const_iterator end= m_CodingTable.end();
        string strTemp = strRaw;

        for ( ; iter != end; ++iter)
        {
            replace_all_distinct(strTemp, iter->strData, iter->strCoding);
        }

        return strTemp;
    }

    string HuffmanTree::HuffmanDecoding(const string& strEncoded)
    {
        string strTemp = strEncoded;
        string strNew;

        while (strTemp.length() > 0)
        {
            HuffmanCodingTable::const_iterator iter= m_CodingTable.begin();
            HuffmanCodingTable::const_iterator end= m_CodingTable.end();
            for ( ; iter != end; ++iter)
            {
                //replace_all_distinct(strTemp, iter->strData, iter->strCoding);
                size_t nPos = strTemp.find(iter->strCoding);

                if (0 == nPos)
                {
                    //cout << "\n" << strTemp << " ==> \n";
                    strTemp = strTemp.substr(iter->strCoding.length(), strTemp.size()-iter->strCoding.length());
                    //cout << strTemp << endl;
                    strNew += iter->strData;
                    //cout << "\n" << strNew << endl;
                    break;
                }
            }
        }

        return strNew;
    }

    //////////////////////////////////////////////////////////////////////////
    void HuffmanTree_Test1()
    {
        string strRawData = "abdacdcdBAdCCCCdCDdDD";
        string strEncoding;
        string strDecoding;
        HuffmanTree huffmanTree;

        cout << "------------------HuffmanTree_Test1-----------------------\n";
        cout << "Pliantext = "  << strRawData << endl;

        huffmanTree.AddNode(2, "a");
        huffmanTree.AddNode(1, "b");
        huffmanTree.AddNode(2, "c");
        huffmanTree.AddNode(6, "d");
        huffmanTree.AddNode(1, "A");
        huffmanTree.AddNode(1, "B");
        huffmanTree.AddNode(5, "C");
        huffmanTree.AddNode(3, "D");

        huffmanTree.Gnenerate();

        strEncoding = huffmanTree.HuffmanEncoding(strRawData);
        cout << "Encoding = "  << strEncoding << endl;

        strDecoding = huffmanTree.HuffmanDecoding(strEncoding); //
        cout << "Decoding = "  << strDecoding << endl;
        cout << "----------------------------------------------------------\n";

    }

    void HuffmanTree_Test2()
    {
        string strRawData = "abdacdcdBAdCCCCdCDdDD";
        string strEncoding;
        string strDecoding;
        HuffmanTree huffmanTree;

        cout << "------------------HuffmanTree_Test2-----------------------\n";
        cout << "Pliantext = "  << strRawData << endl;

        huffmanTree.AddRawDataToNode(strRawData);
        huffmanTree.Gnenerate();

        strEncoding = huffmanTree.HuffmanEncoding(strRawData);
        cout << "Encoding = "  << strEncoding << endl;

        strDecoding = huffmanTree.HuffmanDecoding(strEncoding); //
        cout << "Decoding = "  << strDecoding << endl;
        cout << "----------------------------------------------------------\n";
    }

    void HuffmanTree_Test3()
    {
        string strRawData = "abdacdcdBAdCCCCdCDdDD";
        string strEncoding;
        string strDecoding;
        HuffmanTree huffmanTree;

        cout << "------------------HuffmanTree_Test3-----------------------\n";
        cout << "Pliantext = "  << strRawData << endl;

        huffmanTree.AddNode(1, "A");
        huffmanTree.AddNode(1, "B");
        huffmanTree.AddNode(5, "C");
        huffmanTree.AddNode(3, "D");
        huffmanTree.AddNode(2, "a");
        huffmanTree.AddNode(1, "b");
        huffmanTree.AddNode(2, "c");
        huffmanTree.AddNode(6, "d");

        huffmanTree.Gnenerate();

        strEncoding = huffmanTree.HuffmanEncoding(strRawData);
        cout << "Encoding = "  << strEncoding << endl;

        strDecoding = huffmanTree.HuffmanDecoding(strEncoding); //
        cout << "Decoding = "  << strDecoding << endl;
        cout << "----------------------------------------------------------\n";
    }
}




猜你喜欢

转载自jacky-dai.iteye.com/blog/2307964