数据结构(C描述)笔记---哈夫曼编码

本文详细介绍了哈夫曼编码的原理,包括等长与不等长编码的区别,重点展示了如何通过构建哈夫曼树为字母分配权值,并提供了C语言实现的Huffman编码算法。通过实际例子演示了如何生成并打印每个字符的哈夫曼编码。
摘要由CSDN通过智能技术生成

编码

给每一个对象标记一个二进制位串来表示一组对象。
例如:ASCII,指令系统

编码分类

  1. 等长编码:表示一组对象的二进制位串的长度相等。
  2. 不等长编码:表示一组对象的二进制位串的长度不相等。

前缀编码

前缀编码:一组编码中任一编码都不是其它任何一个编码的前缀。(保证解码时不会有多种可能性)

例题加代码

我们假设给每个字母分配权值:a:45,b:13,c:12,D:16,e:9,f:5,首先按照它们的权值进行构造哈夫曼树
将所有权值左分支改为0右分支改为1. 就是前缀
哈夫曼编码
源文件

#include<stdio.h>
#include<stdlib.h>
#include"HuffmanTree.h"

//哈夫曼编码方案:从叶子结点到根结点逆向求每个字符的哈夫曼编码
//参数:已创建的哈夫曼树,存储哈夫曼编码的数组,n为叶子结点个数
void huffmanCoding(struct element huffTree[],char*** huffCode,int n)
{
    *huffCode =(char**)malloc(n*sizeof(char*));
    //定义工作空间,存储临时产生的编码串
    char temp[n];
    temp[n-1]='\0';
    //遍历哈夫曼树数组,生成哈夫曼编码
    int i,start,pos,parent;
    for(i=0;i<n;i++)
    {
        start = n-1;
        pos = i;
        //找到父结点
        parent = huffTree[i].parent;
        while(parent!=-1)//父结点不是根结点
        {
            //判断是左孩子还是右孩子
            if(huffTree[parent].lchild == pos)
                temp[--start] = '0';
            else
                temp[--start] = '1';

            //当前位置移动到父结点
            pos = parent;
            //更新父结点
            parent = huffTree[parent].parent;
        }
        //n-1-start+1=n-start为数组长度(有'\0')
        (*huffCode)[i] = (char*)malloc((n-start)*sizeof(char));
        int j;
        for(j=0;j<n-start;j++)
            (*huffCode)[i][j]=temp[start+j];
            puts((*huffCode)[i]);
    }
}

int main()
{

 int n=1;
    printf("请输入结点个数:");
    scanf("%d",&n);
    printf("请输入%d个权值:",n);
    int w[n];
    int i;
    for(i=0;i<n;i++)
    scanf("%d",&w[i]);

    struct element huffTree[2*n-1];
    HuffmanTree(huffTree,w,n);

    puts("哈夫曼编码如下:");
    char**huffCode;
    huffmanCoding(huffTree,&huffCode,n);
    system("pause>nul");
    return 0;
}

HuffmanTree.h文件

#include<stdio.h>
#include<stdlib.h>
struct element
{
    int weight;//权重
    int parent,lchild,rchild;//双亲,孩子  保存的是下标
};

void select(struct element huffTree[],int n,int* min,int* mi)
{
    int tw[n];
    int tn[n];
    int i,k,j=0;
    for(i=0;i<n;i++)
    {
        if(huffTree[i].parent==-1)
        {
            tn[j]=i;
            tw[j]=huffTree[i].weight;
            j++;
        }

    }

    int t;
     for(i=0;i<j-1;i++)
        for(k=0;k<j-1-i;k++)
        {
            if(tw[k]>tw[k+1])
            {
                t=tw[k];
                tw[k]=tw[k+1];
                tw[k+1]=t;

                t=tn[k];
                tn[k]=tn[k+1];
                tn[k+1]=t;
            }

        }

        *min=tn[0];
        *mi=tn[1];



}

void HuffmanTree(struct element huffTree[],int w[],int n)
{
    //初始化所有结点的项目为-1
    int i,min,mi;
    for(i=0;i<2*n-1;i++)
    {
        huffTree[i].lchild=-1;
        huffTree[i].rchild=-1;
        huffTree[i].parent=-1;
    }

    //初始化前n个结点的权值
    for(i=0;i<n;i++)
        huffTree[i].weight=w[i];

    for(i=n;i<2*n-1;i++)
    {
         select(huffTree,i,&min,&mi);
         printf("最小下标:%d,次小下标:%d\n",min,mi);
         huffTree[i].weight=huffTree[min].weight+huffTree[mi].weight;
         huffTree[min].parent=i;
         huffTree[mi].parent=i;
         huffTree[i].lchild=min;
         huffTree[i].rchild=mi;
    }
}



运行结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值