#include<iostream> #include<string> #include<vector> using namespace std; #define N 4 //typedef char* HuffmanCode; //动态分配数组存储赫夫曼编码表 int wt[N]={7,5,2,4}; //N个权值,分别对应A(7),B(5),C(2),D(4) template<class T> class HuffmanTree { public: void HuffmanCoding(HuffmanTree<T> *&HT,vector<string> &HC,const int *w,int n); void SelectTree(HuffmanTree *HT,int x,int &s1,int &s2); private: T weight; //权重 T parent,lchild,rchild; }; template<class T> void HuffmanTree<T>::HuffmanCoding(HuffmanTree *&HT,vector<string> &HC,const int *w,int n) { //w存放n个字符的权值(均>0),构造赫夫曼数HT,并求出n个字符的赫夫曼编码HC if(n<=1) exit(-1); int m=2*n-1; //生成的HuffmanTree中结点数目 HT=new HuffmanTree<T>[m+1]; //0号单元未用 HuffmanTree<T> *p=HT; p++; for(int i=1;i<=n;i++) {//根据给定的n个权值,构造n个带权值的根结点 p->weight=*w;p->parent=0;p->lchild=0;p->rchild=0; p++;w++; }//for for(int i=n+1;i<=m;i++) {//HuffmanTree中不带权值的空白结点 p->weight=0;p->parent=0;p->lchild=0;p->rchild=0; p++; }//for for(int i=n+1;i<=m;i++) //建赫夫曼树 { int s1,s2; SelectTree(HT,i-1,s1,s2); HT[s1].parent=i;HT[s2].parent=i;//被使用的树被标记 HT[i].lchild=s1;HT[i].rchild=s2;HT[i].weight=HT[s1].weight+HT[s2].weight;//构建新的树 }//for //--------从叶子到根逆向求每个字符的赫夫曼树--------- for(int i=1;i<=n;i++) { int c=i; T f=HT[i].parent; while(f!=0) { if(HT[f].lchild==c) //结点是其双亲的左结点 HC[i].push_back('0'); else HC[i].push_back('1'); c=f; f=HT[f].parent; }//while reverse(HC[i].begin(),HC[i].end()); }//for }//HuffmanTrees*/ template<class T> void HuffmanTree<T>::SelectTree(HuffmanTree *HT,int x,int &s1,int &s2) { int i,j,firstmin,secondmin; for(i=1;i<=x;i++) //将还未被选中的第一颗HuffmanTree的标号赋给firstmin和secondmin { if(HT[i].parent!=0) //跳过已经被选中的树结点树 continue; else { firstmin=i,secondmin=i; break; }//else }//for for(j=i;j<=x;j++) //由于前i-1颗树已被判定为使用过,故从第i颗数开始遍历 { if(HT[j].parent==0) //跳过父结点不是0的结点 { if(HT[j].weight<HT[firstmin].weight) { secondmin=firstmin;//由于firstmin中每次比较都是存储最小标号 //当firstmin得到一个更小标号时,其当前标号便成为次小标号,赋给secondmin firstmin=j; //将weight<HT[firstmain].weight的标号赋给firstmin }// else if(HT[j].weight>=HT[firstmin].weight&&HT[j].weight<HT[secondmin].weight) {//当secondmin<i<=firstmin secondmin=j; }//else if else continue; }//if }//for if((firstmin==1)&&(secondmin==1)) //余下未被使用的结点的权值均大于第一个结点的权值 {//找出剩余结点中最小的赋给secondmin for(int j=i+1;j<=x;j++) //将接下来未被使用的第一个结点赋给secondmin { if(HT[j].parent==0) { secondmin=j; break; } }//for for(int j=secondmin+1;j<=x;j++)//将余下结点的权值与HT[secondmin].weight进行比较 { if(HT[j].parent==0) { if(HT[j].weight<HT[secondmin].parent) secondmin=j; }//if }//for }//if s1=firstmin;s2=secondmin; }//SelectTree void main() { int n=N; const int *w=wt; HuffmanTree<unsigned int> HTree,*HT; vector<string> HC(N+1); HTree.HuffmanCoding(HT,HC,w,n); cout<<"A,B,C,D依次对应的前缀编码如下:"<<endl; for(int i=1;i<=n;i++) cout<<HC[i]<<endl; }//main