赫夫曼树及其应用

来源:互联网 发布:nginx 修改root路径 编辑:程序博客网 时间:2024/04/28 14:58
#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个字符的赫夫曼编码HCif(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++;}//forfor(int i=n+1;i<=m;i++){//HuffmanTree中不带权值的空白结点p->weight=0;p->parent=0;p->lchild=0;p->rchild=0;p++;}//forfor(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;Tf=HT[i].parent;while(f!=0){if(HT[f].lchild==c)//结点是其双亲的左结点HC[i].push_back('0');elseHC[i].push_back('1');c=f;f=HT[f].parent;}//whilereverse(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}//forfor(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得到一个更小标号时,其当前标号便成为次小标号,赋给secondminfirstmin=j;//将weight<HT[firstmain].weight的标号赋给firstmin}//else if(HT[j].weight>=HT[firstmin].weight&&HT[j].weight<HT[secondmin].weight){//当secondmin<i<=firstminsecondmin=j;}//else ifelsecontinue;}//if}//forif((firstmin==1)&&(secondmin==1))//余下未被使用的结点的权值均大于第一个结点的权值{//找出剩余结点中最小的赋给secondminfor(int j=i+1;j<=x;j++)//将接下来未被使用的第一个结点赋给secondmin{if(HT[j].parent==0){secondmin=j;break;}}//forfor(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}//ifs1=firstmin;s2=secondmin;}//SelectTreevoid 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

0 0