这个类的名字叫huffman Tree,但是不仅仅是生成huffman Tree,因为Huffman树的生成要使用优先队列,也就是堆。stl中其实有这个的实现。但是我机器里的vs2005这个堆的使用有点小bug(估计是stl中使用的就是数组存储,而且数组一旦固定大小,就再也无法改变,其实这样实现失去了堆的某些特性。所以我还是自己实现了一下。顺便练习下。)。刚开始的时候就采用int作为编码的存储单元。后来发现huffman是可变长编码。所以使用int作为编码单元就失去了huffman的特性。于是寻找bit数组。找到了bitset这个stl类,却发现这个是不可变的。无语。只得自己实现一个可变大小的bit vector。然后近乎重写了这个Huffman的编码和解码。不过也不是很难。在这之间又陆陆续续的发现了一系列的bug和编译错误。对以后的编程大有启发。
- /*createdbychicochen
- *date2008/10/25
- */
- #ifndef_HUFFMAN_TREE_
- #define_HUFFMAN_TREE_
- #include"Heap.h"
- #include"TreeNode.h"
- #include"BinaryTree.h"
- #include<map>
- #include"../../ArithmeticTest/ArithmeticTest/BITVector.h"
- usingnamespacestd;
- //thisclassisusedforthecombinfunctioninhuffmanTreeclass.
- classIntCombin
- {
- public:
- staticintAdd(inti,intj)
- {
- returni+j;
- }
- };
- //thisclassforcomparetreenode
- template<classT>
- classTreeNodeCompare
- {
- public:
- staticboolUp(TreeNode<T>*d1,TreeNode<T>*d2)
- {
- returnLt(d1->getData(),d2->getData());
- }
- staticboolEq(T&d1,T&d2)
- {
- if(d1==d2)
- returntrue;
- returnfalse;
- }
- staticboolGt(T&d1,T&d2)
- {
- if(d1>d2)
- returntrue;
- returnfalse;
- }
- staticboolLt(T&d1,T&d2)
- {
- if(d1<d2)
- returntrue;
- returnfalse;
- }
- };
- //thisclassisforstoringhuffmancode.
- //bitsandthelengthofbits
- classHuffmanCode
- {
- public:
- BITVectorbits;
- intlen;
- HuffmanCode()
- {
- len=0;
- }
- HuffmanCode(constHuffmanCode&codes):bits(codes.bits)
- {
- len=codes.len;
- }
- constHuffmanCode&operator=(constHuffmanCode&codes)
- {
- if(this!=&codes)
- {
- this->len=codes.len;
- this->bits=codes.bits;
- }
- return*this;
- }
- ~HuffmanCode()
- {
- }
- };
- template<classT,classCmp,classCombin>
- classHuffmanTree:publicBinaryTree<T>
- {
- private:
- //storethedata,andsortit,thenforbuildingahuffmantree
- Heap<TreeNode<T>*,Cmp>huffmanQueue;
- constunsignedintmask;
- //themaxnumbercanbeshifted,ifitisunsignedintthenitwillbe32.
- constintmaxShiftNum;
- TreeNode<T>*initTree()
- //initthehuffmantree
- {
- TreeNode<T>*combinNode=NULL;
- TtempData;
- while(!this->huffmanQueue.IsEmpty())
- {
- //fetchtwosmalldataandgeneratealargedata
- TreeNode<T>*node1=this->huffmanQueue.Top();
- combinNode=node1;
- this->huffmanQueue.RemoveTop();
- if(!this->huffmanQueue.IsEmpty())
- {
- TreeNode<T>*node2=this->huffmanQueue.Top();
- this->huffmanQueue.RemoveTop();
- tempData=Combin::Add(node1->getData(),node2->getData());
- if(Cmp::Lt(node1->getData(),node2->getData()))
- {
- //hereiscomparingthedata1ofnode1andthedata2ofnode2
- //Cmp:Ltmeans'<'andCmp:Gtmeans'>'
- combinNode=newTreeNode<T>(tempData,node1,node2);
- }
- else
- {
- combinNode=newTreeNode<T>(tempData,node2,node1);
- }
- this->huffmanQueue.Insert(combinNode);
- }
- else
- {
- break;
- }
- }
- returncombinNode;
- }
- //thefinalhuffmancode
- map<T,HuffmanCode>huffmanTable;
- voidSelfEncode(TreeNode<T>*subRoot,unsignedintbitcode,intnum,map<T,HuffmanCode>&ht)
- //encodingthedatafromahuffmantree.
- //Theleftbranchis0,andtherightbranchis1
- {
- if(subRoot!=NULL)
- {
- if(subRoot->left==NULL&&subRoot->right==NULL)
- {
- HuffmanCodehc;
- hc.bits.SetInt(bitcode,0,maxShiftNum-num);
- hc.len=maxShiftNum-num;
- ht[subRoot->getData()]=hc;
- return;
- }
- else
- {
- if(num<=0)
- {
- throw"thehuffmanistoodeep!";
- }
- SelfEncode(subRoot->left,bitcode,num-1,ht);
- bitcode=bitcode|(0x80000000>>(maxShiftNum-num));
- SelfEncode(subRoot->right,bitcode,num-1,ht);
- }
- }
- }
- voidDecodeFromTree(TreeNode<T>*subRoot,BITVector&bits,intindex,constint&len,vector<T>&decode)
- //decodingthecode.usethecodetosearchthedatafromthehuffmanTree.
- //hereyoucancreateyouownmap<code,data>deHuffmanTable.
- //butIcannotanalyzethespacethetablewilluse,
- //soIfindthedatabysearchinghuffmantree
- {
- if(index==len)
- {
- if(subRoot->getLeft()==NULL&&subRoot->getRight()==NULL)
- {
- decode.push_back(subRoot->getData());
- return;
- }
- throw"codelengthisnotmatchthebitslength.HuffmanTreeconstructerror.";
- }
- if(subRoot==NULL)
- {
- throw"decodeerror!";
- }
- elseif(subRoot->getLeft()==NULL&&subRoot->getRight()==NULL)
- {
- decode.push_back(subRoot->getData());
- returnDecodeFromTree(this->root,bits,index,len,decode);
- }
- if(bits.Get(index)==0)
- {
- returnDecodeFromTree(subRoot->getLeft(),bits,index+1,len,decode);
- }
- elseif(bits.Get(index)==1)
- {
- returnDecodeFromTree(subRoot->getRight(),bits,index+1,len,decode);
- }
- else
- {
- throw"codeerror!";
- }
- }
- unsignedintFindCodeFromTable(T&data)
- //findthedatacodefromhuffmantable
- //maybenotefficient.
- {
- returnthis->huffmanTable[data];
- }
- public:
- HuffmanTree(Tt[],intn):
- BinaryTree<T>(),mask(0x80000000),maxShiftNum(sizeof(unsignedint)*8)
- //thearrayttypeisT,andthenumberisn
- {
- if(n==0)
- return;
- TreeNode<T>*node;
- for(inti=0;i<n;i++)
- {
- node=newTreeNode<T>(t[i]);
- this->huffmanQueue.Insert(node);
- }
- this->root=initTree();
- }
- ~HuffmanTree()
- {
- //destroy
- }
- voidSelfEncode()
- //convertthehuffmanTreeintohuffmanTable
- //unsignedintcodeis32bits,sothehuffmantreehasonlylessthan33layer.
- {
- strings="";
- SelfEncode(this->root,0,maxShiftNum,this->huffmanTable);
- }
- voidDecode(HuffmanCode&huffmanCode,vector<T>&decode)
- //usebittofindthedatanode.
- {
- returnDecodeFromTree(this->root,huffmanCode.bits,0,huffmanCode.len,decode);
- }
- HuffmanCodeEncode(Tinfo[],intn)
- //nissize
- {
- HuffmanCodehc;
- for(inti=0;i<n;i++)
- {
- hc.bits.SetBitVector(((HuffmanCode)this->huffmanTable[info[i]]).bits,hc.len,((HuffmanCode)this->huffmanTable[info[i]]).len);
- hc.len+=((HuffmanCode)this->huffmanTable[info[i]]).len;
- }
- returnhc;
- }
- voidPrintHuffmanTable()
- //printthehuffmantable
- //printthepairdata<->code
- {
- intlen=this->huffmanTable.size();
- cout<<"i/tdata/tcode/n";
- intcount=0;
- map<T,HuffmanCode>::iteratori=this->huffmanTable.begin();
- for(;i!=this->huffmanTable.end();i++)
- {
- cout<<count++<<"/t"<<(*i).first<<"/t";
- (*i).second.bits.PrintfZeroOne(0,(*i).second.len);
- cout<<endl;
- }
- }
- };
- #endif
这个类设计方面还有些不足之处。比如encode方法
测试一下:
- inta[10]={12,224,33,32,1,91,35,34,36,291};
- HuffmanTree<int,TreeNodeCompare<int>,IntCombin>ht(a,10);
- ht.SelfEncode();
- ht.PrintHuffmanTable();
- ht.printTree();
- cout<<endl;
- intinfo[]={33,34,33};
- HuffmanCodehc=ht.Encode(info,3);
- hc.bits.PrintfZeroOne(0,hc.len);
- vector<int>code;
- ht.Decode(hc,code);
- for(inti=0;i!=code.size();i++)
- {
- cout<<code[i]<<endl;
- }
- return0;