哈弗曼实现(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来对哈弗曼类代码中间结果进行验证。

原文链接: https://www.cnblogs.com/superstargg/p/3155709.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/93394

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月10日 上午2:07
下一篇 2023年2月10日 上午2:08

相关推荐