数据结构--树和二叉树--求解Huffman树和Hffman编码

来源:互联网 发布:制作画册的软件 编辑:程序博客网 时间:2024/06/02 05:44

    首先给出Huffman树的定义:假设有n个权值{w1,w2...wn},试构造一棵有n个叶子结点的二叉树,每个叶子结点带权为wi,则其中带权路径长度最小的二叉树称作最优二叉树或Huffman树。 下面的求解过程一顺序结构存储Huffman树,具体代码如下:

//----Huffman树和Huffman编码的存储表示typedef struct HTNode{    unsigned int weight;    unsigned int parent,lchild,rchild;   void InitHTNode(unsigned int w,unsigned int p,unsigned int l,int r){       weight=w; parent=p; lchild=l; rchild=r;   }}HTNode,*HuffmanTree;  //动态分配数组存储Huffman树typedef char **HuffmanCode;//动态分配数组存储Huffman编码表//在HT[1...n] 中选择parent为0且weight最小的两个结点,其序号分别是s1,s2void Select(HuffmanTree HT,int n,int &s1,int &s2){    //先找最小 s1表示    for(int i=1;i<=n;++i){        if(HT[i].parent==0){            s1=i;            break;        }    }    for(int i=2;i<=n;++i){        if(HT[i].parent==0){            if(HT[s1].weight>HT[i].weight) s1=i;        }    }    for(int i=1;i<=n;++i){        if(HT[i].parent==0&&i!=s1){            s2=i;            break;        }    }    for(int i=2;i<=n;++i){        if(HT[i].parent==0&&i!=s1){            if(HT[s2].weight>HT[i].weight) s2=i;        }    }}//求Huffman编码void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w,int n){    //w存放n个字符的权值(均大于0),构造Huffman树HT,并求出n个字符的Huffman编码    if(n<=1) return;    int m=2*n-1;  //有n个叶子结点的二叉树共有2*-1个结点    HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));    HTNode* p=NULL;    int i=0,s1=0,s2=0;    for(p=HT+1,i=1;i<=n;++i,++p,++w)       p->InitHTNode(*w,0,0,0); //初始化n个叶子结点    for(;i<=m;++i,++p)        p->InitHTNode(0,0,0,0);  //初始化非叶子结点    for(i=n+1;i<=m;++i){ //建立Huffman树        //在HT[1...i-1] 中选择parent为0且weight最小的两个结点,其序号分别是s1,s2        Select(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;    }    //----从叶子到根逆向求每个字符的Huffman编码---    HC=(HuffmanCode)malloc((n+1)*sizeof(char*));  //分配n个字符编码的头指针向量    char * cd=NULL;    cd=(char*)malloc(n*sizeof(char));  //分配求编码的工作空间    cd[n-1]='\0';  //编码结束符    int start=0,f=0;    unsigned int c=0;    for(i=1;i<=n;++i){ //逐个字符求Huffman编码        start=n-1;  //编码结束符位置        for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent){            if(HT[f].lchild==c) cd[--start]='0';            else                cd[--start]='1';        }        HC[i]=(char*)malloc((n-start)*sizeof(char));        strcpy(HC[i],&cd[start]); //从cd复制编码串到HC    }    free(cd);}void PrintHuffmanCode(char * c){    while(*c!=0){        cout<<*c;        ++c;    }    c=NULL;}int main(){    HuffmanTree HT;    HuffmanCode HC;    int w[7]={3,7,4,6,1,5,2};    int n=7;    HuffmanCoding(HT,HC,w,n);    for(int i=1;i<=n;++i){        cout<<i<<":";        PrintHuffmanCode(HC[i]);        cout<<endl;    }    cout<<endl<<endl;    for(int i=1;i<=13;++i){        cout<<i<<" weight:"<<HT[i].weight<<" parent: "<<HT[i].parent<<" lchild: "<<HT[i].lchild<<" rchild: "<<HT[i].rchild<<endl;    }    cout << "Hello world!" << endl;    return 0;}

运行结果:

    一开始写Select(HuffmanTree HT,int n,int &s1,int &s2)函数时候 s1,s2的初始化错误,一定要保证s1,s2对应结点的parent为0。鄙视

0 0
原创粉丝点击