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

 

你可能感兴趣的:(C++)