首页 > 其他分享 >哈夫曼编码-贪心

哈夫曼编码-贪心

时间:2023-05-25 17:02:27浏览次数:39  
标签:编码 哈夫曼 weight int HT Huffman 贪心


哈夫曼树的定义:n个叶结点,权分别为w1,w2,···,wn的二叉树中,带权路径长度WPL最小的二叉树叫哈夫曼树(Huffman Tree ), 即:最优二叉树 

哈夫曼原理:

1)将字符集中每个字符c出现的频率f(c)作为权值
2)根据给定的权值{w1,w2,···,wn}构造n个二叉树F={T1,T2,···,Tn}, 每个Ti只有一个根结点,权为wi。  
3)在F中选取两棵根结点的权值最小的树构成一棵新的二叉树,其根的权值为左右子树根的权值的和。
4)F中删去这两棵树,加上新得的树。

5)重复2)3)直到只剩一棵树。 

tips:在实际操作中步骤2其实只选取权值最小的两个构成一个新节点

编码实现:

1:在算法huffmanTree中,编码字符集中每一字符c的频率是f(c)。以f为键值的优先队列Q用在贪心选择时,有效地确定算法当前要合并的2棵具有最小频率的树。
2:一旦2棵具有最小频率的树合并后,产生一棵新树,频率为其合并频率之和,并将新树插入优先队列Q。

3:经过n-1次的合并后,优先队列中只剩下一棵树,即所要求的树T。

代码实现:

#include <bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f;
typedef struct HTNode
{
    char ch;
    unsigned int weight;
    unsigned int parent, lchild, rchild;
}HTNode, *HuffmanTree;
HuffmanTree HT;
int w[1024];//字符出现的次数
char str[1024];//存储输入的字符
char out[1024];//输出哈夫曼编码
int n;
//挑选两个出现频路最小且未使用的节点
void Select_Two_HTNode(int pos, int &pos1, int &pos2)
{
    int value1, value2;
    value1 = value2 = inf;
    for(int i = 1; i < pos; ++i)
    {
        if(HT[i].parent == 0)
        {
            if(HT[i].weight < value1)
            {
                int temppos = pos1;
                int tempvalue = value1;
                pos1 = i;
                value1 = HT[i].weight;
                if(tempvalue < value2)
                {
                    value2 = tempvalue;
                    pos2 = temppos;
                }
            }
            else
            {
                if(HT[i].weight < value2)
                {
                    pos2 = i;
                    value2 = HT[i].weight;
                }
            }
        }
        else
            continue;
    }
}
void HuffmanCoding()
{
    int m = 2 * n - 1; //哈夫曼数节点的数量
    HT = (HTNode *)malloc(sizeof(HTNode) * (m + 1));
    HuffmanTree p = HT + 1; //第一个节点不用
    //初始化已知的n个节点
    for(int i = 1; i <= n; ++i, ++p)
    {
        p->weight = w[i];
        p->ch = str[i];
        p->parent = p->lchild = p->rchild = 0;
    }
    //初始化其余节点
    for(int i = n + 1; i <= m; ++i, ++p)
        p->weight = p->parent = p->lchild = p->rchild = 0;
    p = HT + n + 1;//开始合并两个节点
    for(int i = n + 1; i <= m; ++i, ++p)
    {
        int pos1, pos2;
        Select_Two_HTNode(i, pos1, pos2);
        p->weight = HT[pos1].weight + HT[pos2].weight;
        p->lchild = pos1, p->rchild = pos2;
        HT[pos1].parent = HT[pos2].parent = i;
    }
}
void inPut()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i)
    {
     getchar();
     scanf("%c %d", &str[i], &w[i]);
    }
//    for(int i = 1; i <= n; ++i)
//        cout << str[i] << " " << w[i];
}
//深度搜索输出
void outPut(int pos, int i)
{
     if(HT[pos].lchild == 0 && HT[pos].rchild == 0)
     {
         printf("字符 %c 的Huffman编码为 %s\n", HT[pos].ch, out);
     }
     else
     {
         out[i] = '0';
         outPut(HT[pos].lchild, i + 1);
         out[i] = '1';
         outPut(HT[pos].rchild, i + 1);
         strcpy(out + i, "");
     }

}
int main()
{
    inPut();
    HuffmanCoding();
    outPut(2 * n - 1, 0);
}

测试样例:

5
a 1
b 2
c 3
d 4

e 5

输出结果

字符 c 的Huffman编码为 00
字符 a 的Huffman编码为 010
字符 b 的Huffman编码为 011
字符 d 的Huffman编码为 10

字符 e 的Huffman编码为 11

哈夫曼编码-贪心_二叉树

例题:

一道例题 Huffman Coding

标签:编码,哈夫曼,weight,int,HT,Huffman,贪心
From: https://blog.51cto.com/u_16129621/6350094

相关文章

  • Python基础之字符编码和文件类型
    字符编码什么事字符编码?什么是字符编码?人类在与计算机交互时,用的都是人类能读懂的字符,如中文字符、英文字符、日文字符等,而计算机只能识别二进制。所以就产生了字符编码'''字符串类型、文本文件的内容都是由字符组成的,但凡涉及到字符的存取,都需要考虑字符编码的问题。字符编......
  • 【编码】ASCII,GBK,UTF-8
    ASCII码128个字符,二进制编码都以0开头   GBK编码占2个字节,二进制编码以1开头1xxxxxxxxxxxxxxx  UTF-8可变长编码方案英文、数字占1个字节,汉字占3个字节  ASCII码编码0xxxxxxx2字节的汉字开头必须110xxxxx10xxxxxx3字节的汉字开头必须1110xxxx......
  • GB28181-2022中的封装编码要求
    术语: GB28181的传输要求:   国标协议的封装和编码要求:注意国标GB28181只支持RTP+PS;尽管RTP内的内容可以是PS/TS/ES,但是国标协议传输的只是RTP+PS,PS封装的编码类型可以有多种; 国标码流RTP-PS内部的一些参数【PSM,PT等】:  如果不限制国标流,RTP内部可以是PS......
  • 哈夫曼树
    哈夫曼树哈夫曼博士引例判断树:用于分类过程的二叉树.如果采用右面的方法建立二叉树则需要比较31500次我们还可以采用左边的方法建立树需要比较22000次显然两种判别树的效率是不一样的能不能找到效率最高的判别树?哈夫曼树(最优二叉树)......
  • 【IntelliJ IDEA】UTF-8编码下\u7528\u6237转换为中文汉字,\u9489\u9489\u81EA\u
    本文目录一、背景描述二、问题原因三、解决方案一、背景描述本地开发环境,Windows10+IntelliJIDEA+Springboot项目。在开发项目中遇见设置文件编码格式为UTF-8,但是打开该文件出现类似\u9489\u9489\u81EA\u5B9A\u4E49\u673A\u5668\u4EBA这样的数据,看也看不懂,也不是平常见到的......
  • 调用EasyCVR平台base64编码接口转换图片,格式出现异常是什么原因?
    EasyCVR视频融合平台基于云边端智能协同架构,具有强大的设备接入、视频汇聚管理、全网分发、按需调阅、鉴权播放、智能分析等视频能力与服务。平台开放度高、兼容性强、可支持灵活拓展与第三方集成。有用户反馈,获取通道实时快照的返回结果,放到在线转换为图片的工具中出现了转换失......
  • 调用EasyCVR平台base64编码接口转换图片,格式出现异常是什么原因?
    EasyCVR视频融合平台基于云边端智能协同架构,具有强大的设备接入、视频汇聚管理、全网分发、按需调阅、鉴权播放、智能分析等视频能力与服务。平台开放度高、兼容性强、可支持灵活拓展与第三方集成。有用户反馈,获取通道实时快照的返回结果,放到在线转换为图片的工具中出现了转换失败......
  • 贪心算法
    //区间选点//数轴上有n个闭区间[a_i,b_i]。取尽量少的点,使得每个区间内都至少有一个点(不同区间内含的点可以是同一个)////Input//第一行1个整数N(N<=100)//第2~N+1行,每行两个整数a,b(a,b<=100)//INPUT:2//15//46//OUTPUT:1#include<bits/stdc++.h>usingnamespace......
  • 第五章 5.5.1 哈夫曼树
    哈夫曼树带权路径长度定义构造哈夫曼编码带权路径长度哈夫曼树哈夫曼树的构造另一种构造方式哈夫曼编码固定长度编码可变长度编码->允许对不同字符用不等长的二进制位表示前缀编码->没有歧义知识回顾......
  • c++ base64 编码
    #include<iostream>#include<string>#include<vector>#include<cryptopp/base64.h>#include<cryptopp/filters.h>std::stringBinaryToBase64(conststd::vector<unsignedchar>&data){std::stringencoded;C......