哈夫曼编码--贪心策略

哈夫曼编码还是在暑假时候看的,那时候并没有看懂因为比较菜(虽然现在也是很菜的),在《趣学算法》一书中这个问题讲解十分到位,我这篇博客真的是难以望其项背,只能对其进行一点借鉴和摘抄吧

哈夫曼编码是一棵树,权值越大的节点越靠近树根,越小的节点就越远离树根,从他的定义来看,首先想到的应该是贪心策略吧,没错就是贪心算法

虽然说是贪心算法,但是还要知道它 的实现方式啊,他的贪心策略是:每次从树的集合中取出没有双亲且权值最小的两棵树作为左右子树,并合并他们

步骤 :

  1 :确定合适的数据结构(要知道他的左右子树,双亲,权值)

  2:初始化,构造n颗节点为n的字符单节点树集合T={t1,t2,t3,t4···········tn},并且每棵树只有树根

  3:如果集合中只剩下一棵树,那么哈夫曼树就构造成功,直接跳转到步骤6,否则就是从集合中继续拿出没有双亲的左右子树x,y,并将它们合并到一颗z树中,

    z的权值为左右子树权值之和

  4:从T集合中删除x,y 把新树z加入到集合T中

  5:重复步骤3~4

  6:约定左分支上的编码都是0,有分支上的编码都是1,从叶子节点开始逆序求出树的编码

图解:(这儿就直接调用这本书上的图片吧,是在太懒不想画图)

  

代码的实现:

#include<bits/stdc++.h>
using namespace std;
#define MAXBIT 100
#define MAXVALUE 10000
#define MAXLEAF 30
#define MAXNODE MAXLEAF*2-1
typedef struct{
    double weight;
    int parent;
    int lchild;
    int rchild;
    char value;
}HNodeType;//?¨ò?μ?ê??úμ?·?±eóDè¨??£????×?úμ?£?×óóòo¢×ó£??1óD′ú±íμ?×?·?
typedef struct{
    int bit[MAXBIT];
    int start;
}HCodeType;//?aê?±à???á11ì?
HNodeType HuffNode[MAXNODE];//?úμ??á11ì?êy×é
HCodeType HuffCode[MAXLEAF];//±à???á11ì?êy×é
/*?ó??à′?aê?11?ì1t·ò?üê÷*/
void HuffmanTree(HNodeType HuffNode[MAXNODE],int n)
{
    /*i,jê??-?·±?á?£?m1,m2ê?×?D?μ?è¨?μ
    x1,x2ê?1t·ò?üê÷×?D?è¨?μ??ó|μ?Dòo?
    */
    int i,j,x1,x2;
    double m1,m2;
//    3?ê??ˉ?úμ?
    for(i=0;i<2*n-1;i++)
    {
        HuffNode[i].lchild=-1;
        HuffNode[i].parent=-1;
        HuffNode[i].rchild=-1;
        HuffNode[i].weight=0;
    }
    for(i=0;i<n;i++)
    {
        cout<<"Please enter the value of every Node "<<i+1<<endl;
        cin>>HuffNode[i].value>>HuffNode[i].weight;
    }
//    11?ì1t?¥?üê÷
    for(i=0;i<n-1;i++)
    {//òa?-?·n-1′?
        m1=m2=MAXVALUE;
        x1=x2=0;
    //?????aê??ò×?D?μ?á????μ
        for(j=0;j<n+i;j++)
        {
            if(HuffNode[j].weight<m1&&HuffNode[j].parent==-1)
            {
                m2=m1;
                x2=x1;
                m1=HuffNode[j].weight;
                x1=j;
            }
            else if(HuffNode[j].weight<m2&&HuffNode[j].parent==-1)
            {
                m2=HuffNode[j].weight;
                x2=j;
            }
        }
        HuffNode[x1].parent=n+i;
        HuffNode[x2].parent=n+i;
        HuffNode[n+i].weight=m1+m2;
        HuffNode[n+i].lchild=x1;
        HuffNode[n+i].rchild=x2;
        cout<<"x1.weight and x2.weight in round "<<i+1<<"\t"
            <<HuffNode[x1].weight<<"\t"<<HuffNode[x2].weight<<endl;//ó?óú2aê?

    }
}
void HuffmanCode(HCodeType HuffCode[MAXLEAF],int n)
{
    HCodeType cd;
    int i,j,c,p;
    for(i=0;i<n;i++)
    {
        cd.start=n-1;
        c=i;
        p=HuffNode[c].parent;
        while(p!=-1)
        {
            if(HuffNode[p].lchild==c)
                cd.bit[cd.start]=0;
            else
                cd.bit[cd.start]=1;
            cd.start--;
            c=p;
            p=HuffNode[c].parent;
        }
        for(j=cd.start+1;j<n;j++)
            HuffCode[i].bit[j]=cd.bit[j];
        HuffCode[i].start=cd.start;
    }
}
int main()
{
    int i,j,n;
    cout<<"Please enter n"<<endl;
    cin>>n;
    HuffmanTree(HuffNode,n);
    HuffmanCode(HuffCode,n);
    for(i=0;i<n;i++)
    {
        cout<<HuffNode[i].value<<": Huffman Code is: ";
        for(j=HuffCode[i].start+1;j<n;j++)
        {
            cout<<HuffCode[i].bit[j];
        }
        cout<<endl;
    }
    return 0;
}

原文地址:https://www.cnblogs.com/acmblog/p/9629736.html

时间: 2024-08-02 13:37:31

哈夫曼编码--贪心策略的相关文章

HDU 1053 Entropy(哈夫曼编码 贪心+优先队列)

传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1053 Entropy Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 7233    Accepted Submission(s): 3047 Problem Description An entropy encoder is a data

最小优先队列实现赫夫曼树 贪心策略

使用 最小优先队列存放要编码的key,和合并之后内部节点,注意最小优先队列,获得最小值时会把最小是删掉,下面是java实现. package Algorithms; class MinQueue<T extends Comparable<? super T>>{ int heapSize; T[] heap; int capacity; public MinQueue(int capaticty) { this.capacity=capaticty; heapSize=0; //因

贪心算法-霍夫曼编码

霍夫曼编码是一种无损数据压缩算法.在计算机数据处理中,霍夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编码表是通过一种评估来源符号出现机率的方法得到的,出现机率高的字母使用较短的编码,反之出现机率低的则使用较长的编码,这便使编码之后的字符串的平均长度.期望值降低,从而达到无损压缩数据的目的.例如,在英文中,e的出现机率最高,而z的出现概率则最低.当利用霍夫曼编码对一篇英文进行压缩时,e极有可能用一个比特来表示,而z则可能花去25个比特(不是26).用普通的表示方法时,每个

贪心算法应用-哈夫曼编码

哈夫曼编码应用于数据文件和图像压缩的编码方式.其压缩率通常在20%~90%之间.在进行远距离通信时,通常需要把将要传送的文字转换为由二进制字符组成的字符串,并使要传送的电文总长度尽可能的短.显然只要将点文章出现次数多的字符采用尽可能短的编码,就可以减少要传送的电文总长度. 哈夫曼编码的核心思想: (1)每一个字符用一个0,1串作为其代码,并要求任意一个字符的代码都不是其他字符代码的前缀. (2)用字符在文件中出现的频率来建立一个用0,1串表示各字符的最优表示方式,即使出现频率高的字符获得较短编码

霍夫曼编码求节省空间

霍夫曼编码将频繁出现的字符采用短编码,出现频率较低的字符采用长编码.具体的操作过程为:i)以每个字符的出现频率作为关键字构建最小优先级队列:ii)取出关键字最小的两个结点生成子树,根节点的关键字为孩子节点关键字之和,并将根节点插入到最小优先级队列中,直至得到一棵最优编码树. 霍夫曼编码方案是基于______策略的.用该方案对包含a到f6个字符的文件进行编码,文件包含100000个字符,每个字符的出现频率(用百分比表示)如表1-3所示,则与固定长度编码相比,该编码方案节省了______存储空间.

哈夫曼编码

   1.问题描述 哈夫曼编码是广泛地用于数据文件压缩的十分有效的编码方法.其压缩率通常在20%-90%之间.哈夫曼编码算法用字符在文件中出现的频率表来建立一个用0,1串表示各字符的最优表示方式.一个包含100,000个字符的文件,各字符出现频率不同,如下表所示. 有多种方式表示文件中的信息,若用0,1码表示字符的方法,即每个字符用唯一的一个0,1串表示.若采用定长编码表示,则需要3位表示一个字符,整个文件编码需要300,000位:若采用变长编码表示,给频率高的字符较短的编码:频率低的字符较长的

0-1 背包问题、背包问题、最优装载问题、哈夫曼编码,这几个问题的思想是什么?

0-1背包问题: 给定n种物品和一个背包.物品i的重量是Wi,其价值为Vi,背包的容量为C.应如何选择装入背包的物品,使得装入背包中物品的总价值最大? 在选择装入背包的物品时,对每种物品i只有2种选择,即装入背包或不装入背包.不能将物品i装入背包多次,也不能只装入部分的物品i. 背包问题: 与0-1背包问题类似,所不同的是在选择物品i装入背包时,可以选择物品i的一部分,而不一定要全部装入背包,1≤i≤n. 解决方法:求每个物品的价值重量比,即价值/重量.然后添加价值重量比最大的物品,添加结束如果

基于python的二元霍夫曼编码译码详细设计

一.设计题目 对一幅BMP格式的灰度图像(个人证件照片)进行二元霍夫曼编码和译码 二.算法设计 (1)二元霍夫曼编码: ①:图像灰度处理: 利用python的PIL自带的灰度图像转换函数,首先将彩色图片转为灰度的bmp图像,此时每个像素点可以用单个像素点来表示. ②:二元霍夫曼编码: 程序流程图: 详细设计: 统计像素点频率,首先通过python自带的PIL库的图像像素点读取函数read()获取灰度图像的所有像素点,通过循环遍历每个像素点,将每个出现的像素点值以及其次数以键值对的形式放入到pyt

哈夫曼树与哈夫曼编码

哈夫曼树与哈夫曼编码 术语: i)路径和路径长度 在一棵树中,从一个结点往下可以达到的孩子或孙子结点之间的通路,称为路径. 路径中分支的数目称为路径长度.若规定根结点的层数为1,则从根结点到第L层结点的路径长度为L-1. ii)结点的权及带权路径长度 若对树中的每个结点赋给一个有着某种含义的数值,则这个数值称为该结点的权. 结点的带权路径长度为:从根结点到该结点之间的路径长度与该结点的权的乘积. iii)树的带权路径长度 树的带权路径长度:所有叶子结点的带权路径长度之和,记为WPL. 先了解一下