编程练习——huffman编码

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

 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值