哈夫曼编码

来源:互联网 发布:淘宝客服视频教程 编辑:程序博客网 时间:2024/06/05 02:12
今天中秋节,同学都回家了,自己离家太远待在宿舍无聊就看看哈夫曼代码,顺手写了写,特此博客一篇,望多多指教:
对一组数进行哈夫曼树的构建:
假设有n个权值,则构造出的哈夫曼树有n个叶子结点。 n个权值分别设为 w1、w2、…、wn,则哈夫曼树的构造规则为:
(1) 将w1、w2、…,wn看成是有n 棵树的森林(每棵树仅有一个结点);
(2) 在森林中选出两个根结点的权值最小的树合并,作为一棵新树的左、右子树,且新树的根结点权值为其左、右子树根结点权值之和;
(3)从森林中删除选取的两棵树,并将新树加入森林;
(4)重复(2)、(3)步,直到森林中只剩一棵树为止,该树即为所求得的哈夫曼树。[2]
代码如下:
void select(HuffmanTree ht,int n,int *s1,int *s2){    int min1 = INF;    int min2 = INF;    int i;    *s2 = 0;     *s1 = 0;     for(i = 1; i <= n; i++)    {        if(ht[i].weight <= min1 && ht[i].parent == 0)//为了下一个次查找排除查找过得节点        {            min1 = ht[i].weight;            *s1 = i;        }    }    for(i = 1; i <= n; i++)    {        if(ht[i].weight <= min2 && ht[i].parent == 0 && i != *s1)        {            min2 = ht[i].weight;            *s2 = i;        }    }}void InitHuffman(HuffmanTree ht,int w[],int n){    int i;    int m;    //1-n号单元存放叶子节点,初始化    for( i = 1; i <= n; i++)    {        ht[i].weight = w[i-1];        ht[i].parent = 0;        ht[i].LChild = 0;        ht[i].RChild = 0;    }    //n+1—m号单元存放非叶子节点,初始化    m = 2*n - 1;    for(i = n+1; i <= m; i++)    {        ht[i].weight = 0;        ht[i].parent = 0;        ht[i].LChild = 0;        ht[i].RChild = 0;    }}void CrtHuffmanTree(HuffmanTree ht,int w[],int n){    int s1,s2;    InitHUffman(ht,w,n);    for(i = n+1; i<= m; i++)    {//创建哈夫曼树        select(ht,i-1,&s1,&s2);//从0至(i-1)行中选最小的两个值        ht[i].weight = ht[s1].weight + ht[s2].weight;        ht[s1].parent = i;        ht[s2].parent = i;        ht[i].LChild = s1;        ht[i].RChild = s2;    }}
这时候二叉树就构建成功了,如果想进行编码,则直接遍历每一个叶子节点就OK
得到编码
void CrtHuffmanCode(HuffmanTree ht,HuffmanCode hc,int n){    char *cd;    int i;    int c;    int start;    int p;    cd = (char*)malloc((n+1)*sizeof(char));//分配当前编码的工作空间    cd[n-1] = '\0';//从右向左逐位存放编码,首先存放编码结束符    for(i = 1; i <= n; i++)    {        start = n-1;//cd中的位置        c = i;//第几个点        p = ht[i].parent;        while(p != 0)        {            --start;            if(ht[p].LChild == c)            {//左分支标0                cd[start] = '0';            }            else            {//右分支标1                cd[start] = '1';            }            c = p;            p = ht[p].parent;        }        //为第i个编码分配空间        hc[i] = (char*)malloc((n-start)*sizeof(char));        strcpy(hc[i],&cd[start]);//把编码复制到hc[i]里面    }}
同时祝自己中秋节快乐
原创粉丝点击