码迷,mamicode.com
首页 > 其他好文 > 详细

哈弗曼编码

时间:2015-07-28 21:06:14      阅读:104      评论:0      收藏:0      [点我收藏+]

标签:哈弗曼   编码   

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#define MY_STRMAX 100  
#define infinity  1000000  
  
typedef struct  
 {  
   unsigned int weight;         //深度  
   char ch;                     //结点数值  
   unsigned int parent;         //双亲  
   unsigned int lchild;         //左孩子  
   unsigned int rchild;         //右孩子  
}HTNode,*HuffmanTree;           //动态分配数组存储赫夫曼树  
typedef char **HuffmanCode;     //动态分配数组存储赫夫曼编码表  

#include "Huffmantree.h"  
  
  
int Min( HuffmanTree t,int n )  
{ /* 返回i个结点中权值最小的树的根结点序号,函数select()调用 */  
    int i,flag;  
    unsigned int f = infinity; // 取f为不小于可能的值  
    for(i = 1;i <= n; i++)  
        if( t[i].weight < f && t[i].parent == 0 ) // t[i]是树的根结点   
            f = t[i].weight,flag = i;  
        t[flag].parent = 1; // 给选中的根结点的双亲赋1,避免第2次查找该结点   
        return flag;  
}  
  
  
void Select( HuffmanTree *t,int n,int *s1,int *s2 )  
{ /* 在i个结点中选择2个权值最小的树的根结点序号,s1为其中序号小的那个 , s2为其中序号次小的那个 */  
    int x;  
    *s1=Min(*t,n);  
    *s2=Min(*t,n);  
    if((*t)[*s1].weight  > (*t)[*s2].weight )  
    {  
        x = *s1;  
        *s1 = *s2;  
        *s2 = x;  
    }  
}  
  
void HuffmanCoding(HuffmanTree *HT,HuffmanCode *HC,int *w,int n)   
{ /*w存放n个字符的权值(均>0),构造赫夫曼树HT,并求出n个字符的赫夫曼编码HC */  
    int m,i,s1,s2,start,num=0;  
    unsigned int c,f;  
    HuffmanTree p;  
    char *cd;  
    if(n<=1)  
        return;  
    m=2*n-1;    //开辟的空间 比元素个数多 因为后续生成的新子树要用到  
    *HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); /* 0号单元未用 */  
    for(p=*HT+1,i=1;i<=n;++i,++p,++w,++num)//初始化n个叶子结点  
    {  
        (*p).weight=*w;     
        //这部分是给确定的子树赋值,包括字母A-Z权值从数组中得出  
        (*p).parent=0;  
        (*p).lchild=0;  
        (*p).rchild=0;  
    }  
    for(;i<=m;++i,++p)  
        (*p).parent=0;  
    for(i=n+1;i<=m;++i) /* 建赫夫曼树 */  
    { //在HT[1~i-1]中选择parent为0且weight最小的两个结点,其序号分别为s1和s2   
        Select(HT,i-1,&s1,&s2);  
        (*HT)[s1].parent=(*HT)[s2].parent=i;     //这部分给后面要用到的新节点 初值  
        (*HT)[i].lchild=s1;  
        (*HT)[i].rchild=s2;                        
        (*HT)[i].weight=(*HT)[s1].weight+(*HT)[s2].weight;  
    }  
      
      
    //赫夫曼编码的求出,保存在HC里面(二维数组)  
      
      
      
    // 从叶子到根逆向求每个字符的赫夫曼编码   
    *HC=(HuffmanCode)malloc((n+1)*sizeof(char*));  
    // 分配n个字符编码的头指针向量([0]不用)   
    cd=(char*)malloc(n*sizeof(char));   
    // 分配求编码的工作空间   
    cd[n-1]='\0';   
    // 编码结束符   
    for(i=1;i<=n;i++)  
    { /* 逐个字符求赫夫曼编码 */  
        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));  
            // 为第i个字符编码分配空间   
            strcpy((*HC)[i],&cd[start]);  
            // 从cd复制编码(串)到HC   
    }  
    free(cd);   
    //释放工作空间   
}  

#include "Huffmantree.h"  
  
int  main()  
{  
       HuffmanTree HT;  
       HuffmanCode HC;  
       int *w,n,i;  
       printf("请输入叶子结点的个数:");  
       scanf("%d",&n);  
       w = (int*)malloc(sizeof(int));  
       for(i = 0;i < n;i++)  
       {  
           printf("请输入第%d个结点的权值:",i+1);  
           scanf("%d",w+i);  
       }  
       for(i = 1;i <= n;i++)  
       {  
           printf("哈夫曼编码:");  
           puts(HC[i]);  
       }  
       for(i = 0;i <= n;i++)  
       {  
           free(HC[i]);  
       }  
       free(HC);  
       free(HT);  
       return 0;  
}  

版权声明:本文为博主原创文章,未经博主允许不得转载。

哈弗曼编码

标签:哈弗曼   编码   

原文地址:http://blog.csdn.net/weichanjuan3/article/details/47111041

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!