• 贪心算法-Huffman算法


    哈夫曼编码是一种编码方式,属于可变字长编码(VLC)的一种,该编码方式是数学家D.A.Huffman于1952年提出的,是用字符在文件中出现的频率表来建立一个用0,1串表示各字符的最优表示方式,称之为最佳编码

    哈夫曼编码是广泛用于数据文件压缩的十分有效的编码方式,其压缩率通常在20%~90%之间,JPEG就是用哈夫曼编码压缩的

    任何一个字符的编码都不能使其他字符编码的前缀,否则译码时将产生二义性 

     哈夫曼算法的构造思想及设计

    1.构造思想

    将所要编码的字符作为叶子节点,在文件中使用频率作为叶子节点的权值,以自底向上的方式、通过n-1次的"合并"运算后构造出最终所要求的树

    核心思想:让权值大的叶子离根最近

    哈夫曼树中节点的存储结构

    n个叶子节点的哈夫曼树共有2n-1个节点,并且需要进行n-1次合并操作。为了便于选取根节点权值最小的二叉树以及进行合并操作,树种每个节点的存储结构为:

    struct HtNode{

    double weight;

    int parent,lchild,rchild;

    };

    其中,weight域表示节点的权值,即为该字符的使用频率,parent域表示节点的双亲节点在数组中的下标;lchild域表示节点的左孩子在数组中的下标;rchild域表示节点的右孩子在数组中的下标

    哈夫曼树的存储结构

    struct HtTree{

    struct HtNode ht[MaxNode];

    int root;

    };

    typedef struct HtTree* PHtTree;

     线性结构上实现的Haffman算法

    //构造具有n个节点的哈夫曼树

    PHtTree Huffman (int n,double w[n])//构造具有n个节点的哈夫曼树

    {

    PHtTree pht;

    //p1,p2用于记录权值最小的两棵树在数组中的位置

    int i,j,p1,p2;

    //min1,min2用于记录两个最小的权值

    double min1,min2;

    if(n<=1) return;

    //动态分配Haffman树的空间

    pht=(PHtTree)malloc(sizeof(struct HtTree));

    pht->ht=(struct HtNode*)malloc (sizeof(struct HtMode)*(2*n-1));

    //初始化,设置ht数组的初始值

    for(i=0;i<2*n-1;i++)

    {

    pht->ht[i].parent=0;

    if(i

    {

    pht->ht[i].weight=w[i];

    }

    else

    {

    pht->ht[i].weight=-1;

    }

    }

    //执行n-1次合并操作,即构造哈夫曼树的n-1个内部节点

    for(i=0;i

    {

    p1=p2=0;

    //相关变量赋初值

    min1=min2=∞;

    for(j=0;j

    {

    if(pht->ht[j].parent==0)

    {

    if(pht->ht[j].weight

    {

    min2=min1;

    min1=pht->ht[j].weight;

    p2=p1;

    p1=j;

    }

    else if(pht->ht[j].weight

    {

    min2=pht->ht[j].weight;

    p2=j;

    }

    }

    pht->ht[p1].parent=n+i;

    pht->ht[p2].parent=n+i;

    pht->ht[n+i].weight=min1+min2;

    pht->ht[n+i].lchild=p1;

    pht->ht[n+i].rchild=p2;

    }

    return pht; 

    }

    //哈夫曼编码算法描述

    注:从叶子到根逆向求每个字符的哈夫曼编码算法

    void HuffmanCode(char** HC,int n,PHtTree pht)

    {

    //每个字符的编码最大长度不会超过n

    char c[n];

    //分配n个字符指针数组的空间

    HC=(char**)malloc(n*sizeof(char*));

    //第n-1单元存储编码串的结束符

    c[n-1]="\0";

    //逐个对n个字符求其哈夫曼编码

    for(i=1;i<=n;i++)

    {

    start=n-1;

    //k,f是两个工作指针,f指向k的父亲

    for(int k=i,f=pht->ht[i].parent;f!=0;k=f,f=pht->ht[k].parent)

    {

    //左边分配0,右边分配1

    if(pht->ht[f].lchild==k)

    {

    c[--start]="0";

    }

    else

    {

    c[--start]="1";

    }

    }

    //为第i个字符编码分配空间

    HC[i]=(char*)malloc((n-start)*sizeof(char));

    strcpy(HC[i],&c[start]);

    }

    }

     其中在选择最小和次小节点时,该代码有错误

     编码使用start,统一了字符串的个数,在输出时可能有错误 

  • 相关阅读:
    ASP.NET MVC-动态网页开发-宿舍管理系统
    C/C++面试常见问题——static关键字的主要用法
    【一周安全资讯1014】交通运输部发布《公路工程设施支持自动驾驶技术指南》;多地网信办对违反数据安全法规企业作出行政处罚
    配置开启Docker2375远程连接与解决Docker未授权访问漏洞
    软件开发工程师笔试记录--关键路径,浮点数计算,地址变换,中断向量,I/O接口,海明码
    讲理论,重实战!阿里内部SpringBoot王者晋级之路全彩小册开源
    企业进行高质量数据管理,实施数据治理的关键是什么?
    【C#】MQTT
    [题] 分解质因数 #质数(素数)
    网页制作基础大二dw作业HTML+CSS+JavaScript云南我的家乡旅游景点
  • 原文地址:https://blog.csdn.net/m0_62089210/article/details/127903698