Huffman Code 编码译码

赫夫曼编码在通讯中应用广泛,赫夫曼树的建树实际上是一个贪心过程,根据所给的字符权值,优先选取权值小的建树,这样子到最后就可以缩短电文的长度。

e.g.

如果有A~H八个字符编码,如下图:
这里写图片描述

实现如下:

#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack> 
#include <string>
#define INF 0x3f3f3f3f
using namespace std;
int s1,s2;
int m;
char str[10]={'$','A','B','C','D','E','F','G','H'};
typedef struct {
    char ch;
    int data;
    int p,lc,rc;
}Htree,*Hufftree;
typedef char* Huffcode;
void select (Hufftree &Ht,int n)
{
    //char *cd;
    int min1,min2;
    min1=min2=INF;//找最小权值
    s1=s2=0;//纪录最小权值的位置
    int i;
    for (i=1;i<=n;i++)
    {
        if (!Ht[i].p)
            if (Ht[i].data<min1)
            {
                min2=min1;
                s2=s1;
                min1=Ht[i].data;
                s1=i;
            }
            else if (Ht[i].data<min2)
            {
                s2=i;
                min2=Ht[i].data;
            }
    }
}
void Huffman(Hufftree &Ht,Huffcode Hc[],int *w,int n)
    {
    int start;
    char *cd;
    int i,c,f;
    if (n<1)
        return;
    m=2*n-1;//静态链表总长度
    Ht=(Htree*)malloc ((m+1)*sizeof(Htree));
    for (i=1;i<=n;i++)
    {
        Ht[i].ch=str[i];
        Ht[i].data=w[i-1];
        Ht[i].p=0;
        Ht[i].lc=-1;
        Ht[i].rc=-1;
    }//录入数据
    for(i=n+1;i<=m;i++)
    {
        Ht[i].data=0;
        Ht[i].lc=-1;
        Ht[i].rc=-1;
        Ht[i].p=0;
    }//初始化
    for (i=n+1;i<=m;i++)
    {
        select(Ht,i-1);
        Ht[s1].p=i;
        Ht[s2].p=i;
        Ht[i].lc=s1;
        Ht[i].rc=s2;
        Ht[i].data=Ht[s1].data+Ht[s2].data;//更新节点权值
    }//
    cd=(char *)malloc (n*sizeof(char));
    start=0;
    cd[n-1]='\0';
    for (i=1;i<=n;i++)
    {
        start=n-1;
        for(c=i,f=Ht[i].p;f!=0;c=f,f=Ht[f].p)
        {
            if (Ht[f].lc==c)
                cd[--start]='0';
            else
                cd[--start]='1';
        }
        Hc[i]=(char*)malloc((n-start)*sizeof(char));
        strcpy (Hc[i],&cd[start]);
    }
}
void decode(Hufftree &Ht)
{
    int i,j=0;
    i=m;
    char b[20];
    printf("输入编码(End #):\n");
    scanf("%s",b);
    printf("Results:\n");
    while(b[j]!='#')
    {
        //printf("%c ",b[j]);
        if(b[j]=='0')
            i=Ht[i].lc;
        else
            i=Ht[i].rc;
        if(Ht[i].lc==-1)
        {
            printf("%c",Ht[i].ch);
            i=m;   //每次译码从头开始
        }
        j++;
    }
    printf("\n");
}
int main ()
{
    Hufftree Ht;
    Huffcode *Hc;
    int w[20];
    int i,n;
    cout<<"Coding"<<endl;
    printf("编码字符个数:\n");
    scanf("%d",&n);
    Hc=(Huffcode*)malloc(n*sizeof(Huffcode));
    printf("编码的字符的频率:\n");
    for (i=0;i<n;i++)
        scanf("%d",&w[i]);
    Huffman(Ht,Hc,w,n);
    printf("字符编码为:\n");
    cout<<"字符  权值  编码"<<endl;
    for (i=1;i<=n;i++)
    {
        printf ("%c    %d     %s\n",str[i],w[i-1],Hc[i]);
    }
    cout<<"Decoding"<<endl;
    decode(Ht);
    return 0;
}  



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值