zoukankan      html  css  js  c++  java
  • 哈弗曼实现(C++)

    HuffmanCode.h

     1 #ifndef HUFFMANCODE_H
     2 #define HUFFMANCODE_H
     3 
     4 enum LRSTATUS
     5 {
     6     LEFTCHILD, //左子树
     7     RIGHTCHILD //右子树
     8 };
     9 
    10 struct HuffmanCode
    11 {
    12     //哈弗曼编码类
    13     int weight; //权值
    14     int * pPath; //路径指针
    15     int pathLength; //路径长度
    16     HuffmanCode() //默认构造函数
    17     {
    18         weight = 0;
    19         pPath = 0;
    20         pathLength = 0;
    21     }
    22     //HuffmanCode(int n) //初始化路径指针成员
    23     //{
    24     //    pPath = new int [n];
    25     //}
    26     //~HuffmanCode() //销毁并释放路径指针成员
    27     //{
    28     //    if (0!=pPath)
    29     //    {
    30     //        delete [] pPath;
    31     //        pPath = 0;
    32     //    }
    33     //}
    34 };
    35 
    36 #endif //HUFFMANCODE_H

    HuffmanNode.h

     1 #ifndef HUFFMANNODE_H
     2 #define HUFFMANNODE_H
     3 
     4 enum NODESTATUS
     5 {
     6     IN_FOREST, //在森林中
     7     OUT_FOREST //不在森林中
     8 };
     9 
    10 struct HuffmanNode
    11 {
    12     //哈弗曼节点结构类
    13     int weight; //节点权值
    14     NODESTATUS flag; //是否在森林里的标志:IN_FOREST为在森林中;OUT_FOREST为不在森林中
    15     HuffmanNode * parent; //双亲指针
    16     HuffmanNode * lChild; //左子树指针
    17     HuffmanNode * rChild; //右子树指针
    18 
    19     HuffmanNode() //初始化成员数据
    20     {
    21         weight = 0;
    22         flag = OUT_FOREST;
    23         parent = 0;
    24         lChild = 0;
    25         rChild = 0;
    26     }
    27 };
    28 
    29 #endif //HUFFMANNODE_H

    HuffmanTree.h

     1 #ifndef HUFFMANTREE_H
     2 #define HUFFMANTREE_H
     3 
     4 #include "HuffmanCode.h"
     5 #include "HuffmanNode.h"
     6 
     7 class HuffmanTree
     8 {
     9     //哈夫曼树类
    10 private:
    11     HuffmanNode * pNode; //哈弗曼节点指针(即哈弗曼树的节点数组)
    12     HuffmanCode * pCode; //哈弗曼编码指针(即哈弗曼树的路径数组)
    13     int * pWeight; //哈弗曼权值指针(即哈弗曼树的权值数组)
    14     int size; //哈弗曼权值数组大小
    15 protected:
    16 public:
    17     HuffmanTree(int * pWeight, int size); //哈夫曼树构造函数
    18     ~HuffmanTree(){}; //哈弗曼树析构函数
    19 
    20     void CreateHuffmanTree(HuffmanNode ** ppNode); //创建哈弗曼树,使用ppNode返回哈弗曼节点数组
    21     void GetHuffmanCode(HuffmanNode * pNode, HuffmanCode ** ppCode); //获取哈弗曼编码,使用ppCode返回哈弗曼路径数组
    22 };
    23 
    24  void FreeHuffmanTree(HuffmanNode ** ppNode); //释放有函数CreateHuffmanTree申请的动态内存
    25  void FreeHuffmanTree(HuffmanCode ** ppCode); //释放有函数GetHuffmanCode申请的动态内存
    26 
    27 #endif //HUFFMANTREE_H

    HuffmanTree.cpp

      1 #include "HuffmanTree.h"
      2 #include <iostream>
      3 #include <iomanip> //for setw()
      4 
      5 using namespace std;
      6 
      7 #define DEBUG
      8 
      9 #define MAX_VALUE 0x7FFFFFFF
     10 #define WIDTH 12
     11 
     12 //************************************
     13 // Method:    HuffmanTree
     14 // FullName:  HuffmanTree::HuffmanTree
     15 // Access:    public 
     16 // Returns:   
     17 // Qualifier: HuffmanTree类构造函数,使用HuffmanTree类之前必须进行类对象初始化
     18 // Parameter: int * pWeight
     19 // Parameter: int size
     20 //************************************
     21 HuffmanTree::HuffmanTree(int * pWeight, int size)
     22 {
     23     this->pWeight = pWeight;
     24     this->size = size;
     25 }
     26 
     27 //************************************
     28 // Method:    CreateHuffmanTree
     29 // FullName:  HuffmanTree::CreateHuffmanTree
     30 // Access:    public 
     31 // Returns:   void
     32 // Qualifier: 创建哈弗曼树,返回指向保存哈弗曼树节点数组的指针
     33 // Parameter: HuffmanNode * * ppNode
     34 //************************************
     35 void HuffmanTree::CreateHuffmanTree(HuffmanNode ** ppNode)
     36 {
     37     _ASSERT(pWeight || ppNode); //判断是否是空指针
     38 
     39     int nodeNum = 2*size-1; //哈弗曼树总节点数
     40     if (nodeNum<=0)
     41         return ; //出现错误退出函数
     42     pNode = new HuffmanNode [nodeNum];
     43     _ASSERT(pNode);
     44     for (int i=0 ; i<size ; ++i) //赋初值
     45     {
     46         pNode[i].weight = pWeight[i];
     47         pNode[i].flag = IN_FOREST;
     48     }
     49     int min1 = MAX_VALUE, min2 = MAX_VALUE; //最小值和次小值
     50     int pos1 = -1, pos2 = -1; //最小值和次小值位置
     51     for (int i=0 ; i<size ; ++i) //遍历所有节点并且赋值
     52     {
     53         for (int j=0 ; j<nodeNum ; ++j) //查找最小值和次小值
     54         {
     55             if (pNode[j].flag==IN_FOREST && pNode[j].weight<min1)
     56             {
     57                 min2 = min1;
     58                 pos2 = pos1;
     59                 min1 = pNode[j].weight;
     60                 pos1 = j;
     61             }
     62             else if (pNode[j].flag==IN_FOREST && pNode[j].weight<min2)
     63             {
     64                 min2 = pNode[j].weight;
     65                 pos2 = j;
     66             }
     67         }
     68         if (-1!=pos1 && -1!=pos2)
     69         {
     70             //生成最小值和次小值的二叉树双亲
     71             pNode[size+i].weight = (pNode[pos1].weight+pNode[pos2].weight);
     72             pNode[size+i].flag = IN_FOREST;
     73             pNode[size+i].lChild = &pNode[pos1];
     74             pNode[size+i].rChild = &pNode[pos2];
     75             pNode[pos1].flag = OUT_FOREST;
     76             pNode[pos1].parent = &pNode[size+i];
     77             pNode[pos2].flag = OUT_FOREST;
     78             pNode[pos2].parent = &pNode[size+i];
     79 #ifdef NODEBUG
     80             cout << "pNode[" << (size+i) << "].weight = " << pNode[size+i].weight << endl;
     81             cout << "pNode[" << (size+i) << "].flag = " << pNode[size+i].flag << endl;
     82             cout << "pNode[" << (size+i) << "].parent = " << pNode[size+i].parent << endl;
     83             cout << "pNode[" << (size+i) << "].lChild = " << pNode[size+i].lChild << endl;
     84             cout << "pNode[" << (size+i) << "].rChild = " << pNode[size+i].rChild << endl;
     85             cout << "pNode[" << (pos1) << "].weight = " << pNode[pos1].weight << endl;
     86             cout << "pNode[" << (pos1) << "].flag = " << pNode[pos1].flag << endl;
     87             cout << "pNode[" << (pos1) << "].parent = " << pNode[pos1].parent << endl;
     88             cout << "pNode[" << (pos1) << "].lChild = " << pNode[pos1].lChild << endl;
     89             cout << "pNode[" << (pos1) << "].rChild = " << pNode[pos1].rChild << endl;
     90             cout << "pNode[" << (pos2) << "].weight = " << pNode[pos2].weight << endl;
     91             cout << "pNode[" << (pos2) << "].flag = " << pNode[pos2].flag << endl;
     92             cout << "pNode[" << (pos2) << "].parent = " << pNode[pos2].parent << endl;
     93             cout << "pNode[" << (pos2) << "].lChild = " << pNode[pos2].lChild << endl;
     94             cout << "pNode[" << (pos2) << "].rChild = " << pNode[pos2].rChild << endl;
     95 #endif //DEBUG
     96             //重置最小值和次小值
     97             min1 = min2 = MAX_VALUE;
     98             //重置最小值和次小值位置
     99             pos1 = pos2 = -1;
    100         }
    101         if (i==size-1)
    102         {
    103             pNode[size+i-1].flag = OUT_FOREST;
    104         }
    105 #ifdef NODEBUG
    106         cout << "node [] = {" << setw(WIDTH) << "weight" << setw(WIDTH) << "flag" << endl;
    107         for (int k=0 ; k<nodeNum ; ++k)
    108         {
    109             cout << setw(11) << " ";
    110             cout << setw(WIDTH) << (pNode[k].flag==0 ? "IN_FOREST" : "OUT_FOREST") << setw(WIDTH) << pNode[k].weight << endl;
    111         }
    112         cout << setw(11) << "}" << endl;
    113 #endif //DEBUG
    114     }
    115 #ifdef NODEBUG
    116     for (int k=0 ; k<nodeNum ; ++k)
    117     {
    118         cout << "pNode[" << (k) << "].weight = " << pNode[k].weight << endl;
    119         cout << "pNode[" << (k) << "].flag = " << pNode[k].flag << endl;
    120         cout << "pNode[" << (k) << "].parent = " << pNode[k].parent << endl;
    121         cout << "pNode[" << (k) << "].lChild = " << pNode[k].lChild << endl;
    122         cout << "pNode[" << (k) << "].rChild = " << pNode[k].rChild << endl;
    123     }
    124 #endif //DEBUG
    125     *ppNode = pNode;
    126 }
    127 
    128 //************************************
    129 // Method:    GetHuffmanCode
    130 // FullName:  HuffmanTree::GetHuffmanCode
    131 // Access:    public 
    132 // Returns:   void
    133 // Qualifier: 创建哈夫曼编码,返回指向哈弗曼编码数组的指针(注:调用该函数前一定要先使用函数CreateHuffmanTree)
    134 // Parameter: HuffmanNode * pNode
    135 // Parameter: HuffmanCode * * ppCode
    136 //************************************
    137 void HuffmanTree::GetHuffmanCode(HuffmanNode * pNode, HuffmanCode ** ppCode)
    138 {
    139     _ASSERT(pNode || ppCode);
    140     if (size<=0)
    141         return ; //终止函数执行
    142 #ifdef NODEBUG
    143     for (int k=0 ; k<size*2-1 ; ++k)
    144     {
    145         cout << "pNode[" << (k) << "].weight = " << pNode[k].weight << endl;
    146         cout << "pNode[" << (k) << "].flag = " << pNode[k].flag << endl;
    147         cout << "pNode[" << (k) << "].parent = " << pNode[k].parent << endl;
    148         cout << "pNode[" << (k) << "].lChild = " << pNode[k].lChild << endl;
    149         cout << "pNode[" << (k) << "].rChild = " << pNode[k].rChild << endl;
    150     }
    151 #endif //DEBUG
    152 
    153     pCode = new HuffmanCode [size];
    154     _ASSERT(pCode);
    155 
    156     for (int i=0 ; i<size ; ++i) //赋值操作
    157     {
    158         pCode[i].weight = pWeight[i]; //权值赋值
    159         int pCode_Length = 0; //临时变量
    160         HuffmanNode * temp = &pNode[i]; //临时变量
    161         while (NULL!=temp->parent)
    162         {
    163             ++pCode_Length;
    164             temp = temp->parent;
    165         }
    166         pCode[i].pathLength = pCode_Length; //路径长度赋值
    167         pCode[i].pPath = new int [pCode[i].pathLength]; //路径数组创建
    168         temp = &pNode[i]; //重新复制临时变量
    169         for (int j=pCode_Length-1 ; j>=0 ; --j) //路径数组赋值
    170         {
    171             if (NULL!=temp->parent)
    172             {
    173                 HuffmanNode * putValue1 = temp->parent->lChild; //DEBUG
    174                 HuffmanNode * putValue2 = temp->parent->lChild; //DEBUG
    175                 if (temp==temp->parent->lChild)
    176                     pCode[i].pPath[j] = LEFTCHILD;
    177                 else
    178                     pCode[i].pPath[j] = RIGHTCHILD;
    179                 temp = temp->parent;
    180             }
    181         }
    182 #ifdef NODEBUG
    183         cout << "code [] = {" << setw(WIDTH) << "weight" << setw(WIDTH) << "pPath" << endl;
    184         cout << setw(11) << " ";
    185         cout << setw(WIDTH) << pCode[i].weight << ", ";
    186         cout << setw(11) << " ";
    187         for (int k=0 ; k<pCode_Length ; ++k)
    188             cout << pCode[i].pPath[k] << ",";
    189         cout << endl;
    190 #endif //DEBUG
    191     }
    192 #ifdef NODEBUG
    193     for (int k=0 ; k<size*2-1 ; ++k)
    194     {
    195         cout << "pNode[" << (k) << "].weight = " << pNode[k].weight << endl;
    196         cout << "pNode[" << (k) << "].flag = " << pNode[k].flag << endl;
    197         cout << "pNode[" << (k) << "].parent = " << pNode[k].parent << endl;
    198         cout << "pNode[" << (k) << "].lChild = " << pNode[k].lChild << endl;
    199         cout << "pNode[" << (k) << "].rChild = " << pNode[k].rChild << endl;
    200     }
    201 #endif //DEBUG
    202     *ppCode = pCode;
    203 }
    204 
    205 //************************************
    206 // Method:    FreeHuffmanTree
    207 // FullName:  FreeHuffmanTree
    208 // Access:    public 
    209 // Returns:   void
    210 // Qualifier: 销毁由函数CreateHuffmanTree申请的对象
    211 // Parameter: HuffmanNode * * ppNode
    212 //************************************
    213 void FreeHuffmanTree(HuffmanNode ** ppNode)
    214 {
    215     if (NULL!=ppNode && NULL!=*ppNode)
    216     {
    217         delete [] *ppNode;
    218         *ppNode = NULL;
    219     }
    220 }
    221 
    222 //************************************
    223 // Method:    FreeHuffmanTree
    224 // FullName:  FreeHuffmanTree
    225 // Access:    public 
    226 // Returns:   void
    227 // Qualifier: 销毁由函数GetHuffmanCode申请的内存
    228 // Parameter: HuffmanCode * * ppCode
    229 //************************************
    230 void FreeHuffmanTree(HuffmanCode ** ppCode)
    231 {
    232     if (NULL!=ppCode && NULL!=*ppCode)
    233     {
    234         int size = _msize(*ppCode)/sizeof(HuffmanCode);
    235         for (int i=0 ; i<size ; ++i)
    236         {
    237             if (NULL!=(*ppCode+i)->pPath)
    238             {
    239                 delete [] (*ppCode+i)->pPath;
    240                 (*ppCode+i)->pPath = NULL;
    241             }
    242         }
    243         delete [] *ppCode;
    244         *ppCode = NULL;
    245     }
    246 }

    Main.cpp

     1 #include <iostream>
     2 #include "HuffmanTree.h"
     3 
     4 using namespace std;
     5 
     6 #define DEBUG
     7 
     8 #define _CRTDBG_MAP_ALLOC
     9 #include <stdlib.h>
    10 #include <crtdbg.h>
    11 
    12 #ifndef DBG_NEW
    13 #define DBG_NEW new ( _NORMAL_BLOCK , __FILE__ , __LINE__ )
    14 #define new DBG_NEW
    15 #endif
    16 
    17 int main() //测试代码
    18 {
    19     ::_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
    20     ::_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
    21     ::_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);
    22 
    23     int weight[] = {87, 67, 45, 3, 6, 9, 11};
    24     int size = sizeof(weight)/sizeof(int);
    25 #ifdef DEBUG
    26     cout << "weight [] = {" ;
    27     for (int i=0 ; i<size ; ++i)
    28         cout << weight[i] << ", " ;
    29     cout << "}" << endl;
    30 #endif //DEBUG
    31     HuffmanTree obj(weight, size);
    32     HuffmanNode * pNode = NULL;
    33     obj.CreateHuffmanTree(&pNode);
    34     HuffmanCode * pCode = NULL;
    35     obj.GetHuffmanCode(pNode, &pCode);
    36 
    37     FreeHuffmanTree(&pNode);
    38     FreeHuffmanTree(&pCode);
    39 
    40     return 0;
    41 }

    以上程序共5个文件:

     

    1.Main.cpp文件主要实现对哈弗曼树、哈弗曼编码的测试,并且使用VS专用内存泄露检测代码进行内存泄露检测;

    2.类HuffmanNode主要实现哈弗曼节点结构构造;

    3.类HuffmanCode主要实现对哈弗曼树路径的存储;

    4.类HuffmanTree主要实现哈弗曼树,并且实现创建哈弗曼树,创建哈弗曼编码;

    5.使用宏#define DEBUG来对哈弗曼类代码中间结果进行验证。

    煮酒论英雄
  • 相关阅读:
    hdu 1290 献给杭电五十周年校庆的礼物 (DP)
    hdu 3123 GCC (数学)
    hdu 1207 汉诺塔II (DP)
    hdu 1267 下沙的沙子有几粒? (DP)
    hdu 1249 三角形 (DP)
    hdu 2132 An easy problem (递推)
    hdu 2139 Calculate the formula (递推)
    hdu 1284 钱币兑换问题 (DP)
    hdu 4151 The Special Number (DP)
    hdu 1143 Tri Tiling (DP)
  • 原文地址:https://www.cnblogs.com/superstargg/p/3155709.html
Copyright © 2011-2022 走看看