哈夫曼编码

一、哈夫曼树

1、定义:

      带权路径长度最短的树(最优树)

2、特点:

           (1)权值越大的节点离根结点越近

           (2)哈夫曼数中没有度为1的节点,由二叉树性质

对任意一棵非空二叉树T,如果其终端节点(度为0的节点)数为n0,度为2的节点数为n2,则n0=n2+1;

可知,一棵有n个叶子结点的哈夫曼树共有2n-1个节点,可以存储在一个大小为2n-1的一维数组中

3、创建哈夫曼树

/*定义二叉树的存储结点*/
typedef struct hnode

    int weight;
    int lchild,rchild,parent;
 }HTNode,*HuffmanTree;

/*创建哈夫曼树*/
void CreateHuffman_tree(HuffmanTree &HT,int n)/*建立n个叶子结点的哈夫曼树*/
{
    //初始化
    if(n<=1) return ;//至少2个节点才能形成
    int m=2*n-1;
    HT=new HTNode[m+1];//n个叶子结点的哈夫曼树中共有2n-1个节点,HT[0]不使用,所以申请m+1个单元
    for(int i=1;i<=m;i++)
    {
        HT[i].parent=0;HT[i].lchild=0;HT[i].rchild=0;
    }
    for(int i=1;i<=n;i++)//前n个单元存叶子节点
    {
        scanf("%d",&HT[i].weight);
    }
    //创建
    for(int i=n+1;i<=m;i++)
    {
        int s1,s2;
        Select(HT,i-1,s1,s2);//从HT[k](1<=k<=i-1(当前节点之前))中选2个权值最小的
        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;
    }
}
void Select(HTNode HT[],int len,int &s1,int &s2)//选出权值最小的两个结点,下标通过s1和s2传出去
{
    int i,min1=32767,min2=32767;
    for(i=1;i<=len;i++)
    {
        if(HT[i].weight<min1&&HT[i].parent==0)
        {
            s2=s1;
            min2=min1;
            min1=HT[i].weight;
            s1=i;
        }
        else if(HT[i].weight<min2&&HT[i].parent==0)
        {    min2=HT[i].weight;
            s2=i;
        }
    }
}

二、哈夫曼编码(最优前缀编码)

1、前缀编码:在一个编码方案中,任一个编码都不是其他任何编码的前缀。

2、例题:

编写函数实现哈夫曼编码。输入结点个数(保证个数>1)及各结点的权值,为各结点进行编码。(其中 HT 为哈夫曼树,n 为叶子结点个数, HC 为哈夫曼编码。)

3、算法实现

哈夫曼编码表的存储表示

typedef char **HuffmanCode;

(1)

void   Huffman_code(HuffmanTree HT,HuffmanCode &HC,int n)//求哈夫曼编码
    {
        HC=new char*[n+1];//分配存储n个字符编码的编码表空间(HC[0]不使用)/*二维数组*/
        char *s=new char[n];//分配临时存放每个字符编码的动态数组空间
        s[n-1]='\0';
        for(int i=1;i<=n;i++)
        {
            int c,f,start=n-1;
            c=i;
            f=HT[i].parent;
            while(f)
            {
                --start;
                if(HT[f].lchild==c) s[start]='0';
                else s[start]='1';
                c=f;
                f=HT[f].parent;
            }
            HC[i]=new char[n-start];//为第i个字符编码分配空间
            strcpy(HC[i],&s[start]);
        }
          delete s;
    }

三、完整代码 

#include<stdio.h>
#include<string.h>
#include<malloc.h>
typedef struct hnode
{ 
    int weight;
    int lchild,rchild,parent;
 }HTNode,*HuffmanTree;/*定义二叉树的存储结点*/
typedef char **HuffmanCode;
void Select(HTNode HT[],int len,int &s1,int &s2)//选出权值最小的两个结点,下标通过s1和s2传出去
{
    int i,min1=32767,min2=32767;
    for(i=1;i<=len;i++)
    {
        if(HT[i].weight<min1&&HT[i].parent==0)
        {
            s2=s1;
            min2=min1;
            min1=HT[i].weight;
            s1=i;
        }
        else if(HT[i].weight<min2&&HT[i].parent==0)
        {    min2=HT[i].weight;
            s2=i;
        }
    }
}
void CreateHuffman_tree(HuffmanTree &Ht,int n);/*建立哈夫曼树*/
void Huffman_code(HuffmanTree HT,HuffmanCode &HC,int n);/*哈夫曼树编码*/
void CreateHuffman_tree(HuffmanTree &HT,int n)/*建立n个叶子结点的哈夫曼树*/
{
    //初始化
    if(n<=1) return ;//至少2个节点才能形成
    int m=2*n-1;
    HT=new HTNode[m+1];//n个叶子结点的哈夫曼树中共有2n-1个节点,HT[0]不使用,所以申请m+1个单元
    for(int i=1;i<=m;i++)
    {
        HT[i].parent=0;HT[i].lchild=0;HT[i].rchild=0;
    }
    for(int i=1;i<=n;i++)//前n个单元存叶子节点
    {
        scanf("%d",&HT[i].weight);
    }
    //创建
    for(int i=n+1;i<=m;i++)
    {
        int s1,s2;
        Select(HT,i-1,s1,s2);//从HT[k](1<=k<=i-1(当前节点之前))中选2个权值最小的
        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;
    }
}
void   Huffman_code(HuffmanTree HT,HuffmanCode &HC,int n)//求哈夫曼编码
    {
        HC=new char*[n+1];//分配存储n个字符编码的编码表空间(HC[0]不使用)/*二维数组*/
        char *s=new char[n];//分配临时存放每个字符编码的动态数组空间
        s[n-1]='\0';
        for(int i=1;i<=n;i++)
        {
            int c,f,start=n-1;
            c=i;
            f=HT[i].parent;
            while(f)
            {
                --start;
                if(HT[f].lchild==c) s[start]='0';
                else s[start]='1';
                c=f;
                f=HT[f].parent;
            }
            HC[i]=new char[n-start];//为第i个字符编码分配空间
            strcpy(HC[i],&s[start]);
        }
          delete s;
    }
int main()
{
    HuffmanTree HT;
    HuffmanCode HC;
    int i, n;
    scanf("%d",&n);
    CreateHuffman_tree(HT, n);/*建立哈夫曼树*/
    Huffman_code(HT,HC,n);/*哈夫曼树编码*/
    for(i=1;i<=n;i++)/*输出字符、权值及编码*/
       printf("编码是:%s\n",HC[i]);
    return 0;
}

运行

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值