编程练习——Huffman编码

这个类的名字叫huffman Tree,但是不仅仅是生成huffman Tree,因为Huffman树的生成要使用优先队列,也就是堆。stl中其实有这个的实
现。但是我机器里的vs2005这个堆的使用有点小bug(估计是stl中使用的就是数组存储,而且数组一旦固定大小,就再也无法改变,其实这样实现失去了堆的某些特
性。 _ 所以我还是自己实现了一下 _
。顺便练习下。)。刚开始的时候
就采用int作为编码的存储单元。后来发现huffman是可变长编码。所以使用int作为编码单元就失去了huffman的特性。于是寻找bit数组。找到了bit
set这个stl类,却发现这个是不可变的。无语。只得自己实现一个可变大小的 _ bit vector _

。然后近乎重写了这个Huffman的编码和解码。不过也不是很难。在这之间又陆陆续续的发现了一系列的bug和编译错误。对以后的编程大有启发。

  1. /* created by chico chen
  2. *  date 2008/10/25
  3. */
      1. #ifndef HUFFMAN_TREE
  4. #define HUFFMAN_TREE
  5. #include “Heap.h”
  6. #include “TreeNode.h”
  7. #include “BinaryTree.h”
  8. #include 
  9. #include “…/…/ArithmeticTest/ArithmeticTest/BITVector.h”
  10. using namespace std;
    1. // this class is used for the combin function in huffmanTree class.
  11. class IntCombin
  12. {
  13. public :
  14. static int Add( int i, int j)
  15. {
  16. return i+j;
  17. }
  18. };
    1. // this class for compare tree node
  19. template < class T>
  20. class TreeNodeCompare
  21. {
  22. public :
  23. static bool Up(TreeNode* d1, TreeNode* d2)
  24. {
  25. return Lt(d1->getData(),d2->getData());
  26. }
    1. static bool Eq(T& d1, T& d2)
  27. {
  28. if (d1 == d2)
  29. return true ;
  30. return false ;
  31. }
    1. static bool Gt(T& d1, T& d2)
  32. {
  33. if (d1 > d2)
  34. return true ;
  35. return false ;
  36. }
    1. static bool Lt(T& d1, T& d2)
  37. {
  38. if (d1 < d2)
  39. return true ;
  40. return false ;
  41. }
  42. };
    1. // this class is for storing huffman code.
  43. // bits and the length of bits
  44. class HuffmanCode
  45. {
  46. public :
  47. BITVector bits;
  48. int len;
  49. HuffmanCode()
  50. {
  51. len = 0;
  52. }
    1. HuffmanCode( const HuffmanCode & codes):bits(codes.bits)
  53. {
  54. len  = codes.len;
    1. }
    1. const HuffmanCode& operator=( const HuffmanCode & codes)
  55. {
  56. if ( this != &codes)
  57. {
  58. this ->len = codes.len;
  59. this ->bits = codes.bits;
  60. }
  61. return * this ;
  62. }
    1. ~HuffmanCode()
  63. {
    1. }
  64. };
    1. template < class T, class Cmp, class Combin>
  65. class HuffmanTree: public BinaryTree
  66. {
  67. private :
  68. // store the data, and sort it, then for building a huffman tree
  69. Heap<TreeNode* ,Cmp> huffmanQueue;
    1. const unsigned int mask;
  70. // the max number can be shifted, if it is unsigned int then it will be 32.
  71. const int maxShiftNum;
      1. TreeNode* initTree()
  72. // init the huffman tree
  73. {
  74. TreeNode * combinNode = NULL;
  75. T tempData;
  76. while (! this ->huffmanQueue.IsEmpty())
  77. {
  78. // fetch two small data and generate a large data
  79. TreeNode * node1 = this ->huffmanQueue.Top();
  80. combinNode = node1;
  81. this ->huffmanQueue.RemoveTop();
  82. if (! this ->huffmanQueue.IsEmpty())
  83. {
  84. TreeNode * node2 = this ->huffmanQueue.Top();
  85. this ->huffmanQueue.RemoveTop();
  86. tempData =  Combin::Add(node1->getData(),node2->getData());
      1. if (Cmp::Lt(node1->getData(),node2->getData()))
  87. {
  88. // here is comparing the data1 of node1 and the data2 of node2
  89. //  Cmp:Lt means ‘<’ and Cmp:Gt means ‘>’
    1. combinNode = new TreeNode(tempData,node1,node2);
  90. }
  91. else
  92. {
  93. combinNode = new TreeNode(tempData,node2,node1);
  94. }
  95. this ->huffmanQueue.Insert(combinNode);
  96. }
  97. else
  98. {
  99. break ;
  100. }
    1. }
  101. return combinNode;
  102. }
        1. // the final huffman code
  103. map<T,HuffmanCode> huffmanTable;
      1. void SelfEncode(TreeNode* subRoot,unsigned int bitcode, int num,map<T,HuffmanCode > &ht)
  104. // encoding the data from a huffman tree.
  105. // The left branch is 0, and the right branch is 1
  106. {
    1. if (subRoot != NULL)
  107. {
    1. if (subRoot->left == NULL && subRoot->right==NULL)
  108. {
  109. HuffmanCode hc;
  110. hc.bits.SetInt(bitcode,0,maxShiftNum-num);
  111. hc.len = maxShiftNum-num;
  112. ht[subRoot->getData()] = hc;
  113. return ;
  114. }
  115. else
  116. {
  117. if (num<=0)
  118. {
  119. throw “the huffman is too deep!” ;
  120. }
      1. SelfEncode(subRoot->left,bitcode,num-1,ht);
  121. bitcode = bitcode | (0x80000000 >> (maxShiftNum-num));
  122. SelfEncode(subRoot->right,bitcode,num-1,ht);
  123. }
  124. }
      1. }
      1. void DecodeFromTree(TreeNode* subRoot,BITVector& bits, int index, const int & len,vector& decode)
  125. // decoding the code. use the code to search the data from the huffmanTree.
  126. // here you can create you own map<code,data> deHuffmanTable.
  127. // but I can not analyze the space the table will use,
  128. // so I find the data by searching huffman tree
  129. {
  130. if (index == len)
  131. {
  132. if (subRoot->getLeft()==NULL && subRoot->getRight() == NULL)
  133. {
    1. decode.push_back(subRoot->getData());
  134. return ;
  135. }
  136. throw “code length is not match the bits length. Huffman Tree construct error.” ;
  137. }
  138. if (subRoot == NULL)
  139. {
  140. throw “decode error!” ;
    1. }
  141. else if (subRoot->getLeft() == NULL && subRoot->getRight() == NULL)
  142. {
    1. decode.push_back(subRoot->getData());
  143. return DecodeFromTree( this ->root,bits,index,len,decode);
  144. }
    1. if (bits.Get(index) == 0)
  145. {
  146. return DecodeFromTree(subRoot->getLeft(),bits,index+1,len,decode);
  147. }
  148. else if (bits.Get(index)==1)
  149. {
    1. return DecodeFromTree(subRoot->getRight(),bits,index+1,len,decode);
  150. }
  151. else
  152. {
  153. throw “code error!” ;
  154. }
      1. }
      1. unsigned int FindCodeFromTable(T& data)
  155. // find the data code from huffman table
  156. // may be not efficient.
  157. {
  158. return this ->huffmanTable[data];
  159. }
    1. public :
    1. HuffmanTree(T t[], int n):
  160. BinaryTree(),mask(0x80000000),maxShiftNum( sizeof (unsigned int )*8)
  161. // the array t type is T, and the number is n
  162. {
  163. if (n == 0)
  164. return ;
  165. TreeNode* node;
  166. for ( int i = 0; i < n; i++)
  167. {
  168. node = new TreeNode(t[i]);
  169. this ->huffmanQueue.Insert(node);
  170. }
  171. this ->root = initTree();
  172. }
    1. ~HuffmanTree()
  173. {
  174. // destroy
    1. }
      1. void SelfEncode()
  175. // convert the huffmanTree into huffmanTable
  176. // unsigned int code is 32 bits, so the huffman tree has only less than 33 layer.
  177. {
  178. string s= “” ;
    1. SelfEncode( this ->root,0,maxShiftNum, this ->huffmanTable);
    1. }
        1. void Decode(HuffmanCode& huffmanCode,vector& decode)
  179. // use bit to find the data node.
  180. {
    1. return DecodeFromTree( this ->root,huffmanCode.bits,0,huffmanCode.len,decode);
    1. }
    1. HuffmanCode Encode(T info[], int n)
  181. // n is size
  182. {
  183. HuffmanCode hc;
    1. for ( int i = 0; i < n; i++)
  184. {
    1. hc.bits.SetBitVector(((HuffmanCode) this ->huffmanTable[info[i]]).bits,hc.len,((HuffmanCode) this ->huffmanTable[info[i]]).len);
  185. hc.len +=((HuffmanCode) this ->huffmanTable[info[i]]).len;
  186. }
    1. return hc;
  187. }
      1. void PrintHuffmanTable()
  188. // print the huffman table
  189. // print the pair data<->code
  190. {
  191. int len = this ->huffmanTable.size();
  192. cout << “i/tdata/tcode/n” ;
  193. int count = 0;
  194. map<T,HuffmanCode>::iterator i= this ->huffmanTable.begin();
  195. for (; i != this ->huffmanTable.end(); i++)
  196. {
  197. cout << count++<< “/t” <<(*i).first<< “/t” ;
  198. (*i).second.bits.PrintfZeroOne(0,(*i).second.len);
  199. cout<<endl;
  200. }
    1. }
    1. };
      1. #endif

这个类设计方面还有些不足之处。比如encode方法

测试一下:

  1. int a[10] = {12,224,33,32,1,91,35,34,36,291};
  2. HuffmanTree< int ,TreeNodeCompare< int >,IntCombin> ht(a,10);
  3. ht.SelfEncode();
  4. ht.PrintHuffmanTable();
  5. ht.printTree();
  6. cout << endl;
  7. int info[] = {33,34,33};
  8. HuffmanCode hc = ht.Encode(info,3);
  9. hc.bits.PrintfZeroOne(0,hc.len);
  10. vector< int > code;
  11. ht.Decode(hc,code);
  12. ** for ** ( int i = 0; i != code.size();i++)
  13. {
    1. cout<<code[i]<<endl;
  14. }
    1. ** return ** 0;