哈夫曼编码问题(贪心算法)
首先便是理解什么是前缀编码,不等长编码,理解数据压缩的基本方法。
哈夫曼编码是一种十分有效的编码方法,广泛用于数据压缩中,其压缩率通常在 20%~90% 之间。采用不等长编码使编码不会有歧义也就是不二义性,并且和等长编码相比更加节省空间。
贪心算法实现贪心算法主要思路通过每次查找最小权和次小权构建叶子节点,和作为父节点的权值,如此循环下来构成一棵完全二叉树,对应的左子树编码为0,右子树编码为1,通过遍历树即可得出最终的哈夫曼编码。
以下是贪心算法的代码段(PS:最后有所有代码)
int x1, x2, w1, w2;for (int i = 0; i < H - 1; ++i) {x1 = x2 = -1;w1 = w2 = MAXWEIGHT;for (int j = 0; j < H + i; ++j) {//H + i次里面遍历得到最小权重的节点if (haffman[j].parent == -1 && haffman[j].weight < w1) {w2 = w1;x2 = x1;x1 = j;w1 = haffman[j].weight;}else if(haffman[j].parent == -1 && haffman[j].weight < w2) {x2 = j;w2 = haffman[j].weight;}}haffman[H + i].leftChild = x2;haffman[H + i].rightChild = x1;haffman[H + i].weight = w1 + w2; haffman[x1].parent = H + i;haffman[x2].parent = H + i;}
}
这部分代码在循环里在嵌套一个循环,遍历得最小的两个节点。如果每次最小的更新了,那么需要把上次最小的给第二个最小的。两个循环比较复杂,难以理解,每次合成新的节点后都会更新最小的数,if语句同时需要实现复制交换的功能。
这里体现的就是贪心算法
主要思路通过每次查找最小权和次小权构建叶子节点,和作为父节点的权值,如此循环下来构成一棵完全二叉树,对应的左子树编码为0,右子树编码为1,通过遍历树即可得出最终的哈夫曼编码。
输出结果的示例
用二叉数对编码进行表示(手写,有点潦草,嘻嘻)
附上完整代码
#include <iostream>
using namespace std;
//最大字符编码数组长度
#define MAXCODELEN 100
//最大哈夫曼节点结构体数组个数
#define MAXHAFF 100
//最大哈夫曼编码结构体数组的个数
#define MAXCODE 100
#define MAXWEIGHT 10000;
typedef struct Haffman {int weight; //权重char ch; //字符 int parent;//父节点int leftChild;//左孩子节点int rightChild;//右孩子节点
} HaffmaNode;typedef struct Code { int code[MAXCODELEN];//字符的哈夫曼编码的存储int start;//从哪个位置开始
} HaffmaCode;
HaffmaNode haffman[MAXHAFF];
HaffmaCode code[MAXCODE];
void buildHaffman(int H) {//H是输入的需要哈夫曼编码的字符的个数 //哈夫曼节点的初始化之前的工作, weight为0,parent,leftChile,rightChile都为-1for (int i = 0; i < H * 2 - 1; ++i) {haffman[i].weight = 0;haffman[i].parent = -1;haffman[i].leftChild = -1;haffman[i].rightChild = -1;}std::cout << "请输入需要哈夫曼编码的字符和权重大小" << std::endl;for (int i = 0; i < H; i++) {std::cout << "请分别输入第" << i +1<< "个哈夫曼字符和权重" << std::endl;std::cin >> haffman[i].ch;std::cin >> haffman[i].weight;}//每次找出最小的权重的节点,生成新的节点,需要H - 1 次合并int x1, x2, w1, w2;for (int i = 0; i < H - 1; ++i) {x1 = x2 = -1;w1 = w2 = MAXWEIGHT;for (int j = 0; j < H + i; ++j) {//H + i次里面遍历得到最小权重的节点if (haffman[j].parent == -1 && haffman[j].weight < w1) {w2 = w1;x2 = x1;x1 = j;w1 = haffman[j].weight;}else if(haffman[j].parent == -1 && haffman[j].weight < w2) {x2 = j;w2 = haffman[j].weight;}}haffman[H + i].leftChild = x2;haffman[H + i].rightChild = x1;haffman[H + i].weight = w1 + w2; haffman[x1].parent = H + i;haffman[x2].parent = H + i;}
}
void visCode(int H) {HaffmaCode hCode;//保存当前叶子节点的字符编码 int curParent;//当前父节点int c;//下标和叶子节点的编号for (int i = 0; i < H; ++i) {hCode.start = H - 1;c = i; curParent = haffman[i].parent;while (curParent != -1) {/if (haffman[curParent].leftChild == c) {hCode.code[hCode.start] = 1;//左分支赋予0,右分支赋予1} else { hCode.code[hCode.start] = 0;}hCode.start--;c = curParent;curParent = haffman[c].parent;}for (int j = hCode.start + 1; j < H; ++j) {//把当前的叶子节点信息保存到编码结构体里面code[i].code[j] = hCode.code[j];}code[i].start = hCode.start;}
}
int main() {std::cout << "请输入有多少个哈夫曼字符" << std::endl;int H = 0;std::cin >> H;if ( H<= 0) {std::cout << "您输入的个数有误" << std::endl; }buildHaffman(H);visCode(H);for (int i = 0; i < H; ++i) {std::cout << haffman[i].ch << ": Haffman Code is:";//前缀码 for (int j = code[i].start + 1; j < H; ++j) {std::cout << code[i].code[j];}std::cout << std::endl;}return 0;
}
哈夫曼编码问题(贪心算法)相关推荐
- 规范哈夫曼编码和Deflate算法
经过常规的哈夫曼编码以后,我们需要将每个符号对应的码字记录下来,比较容易想到的是按照字母序记录每个字母的编码,这样的好处是字母与码字的映射关系被隐式记录: 假设字母表 A = { a 1 , a 2 ...
- python哈夫曼编码注意_Python 算法(2) 哈夫曼编码 Huffman Encoding
这个问题原始是用来实现一个可变长度的编码问题,但可以总结成这样一个问题,假设我们有很多的叶子节点,每个节点都有一个权值w(可以是任何有意义的数值,比如它出现的概率),我们要用这些叶子节点构造一棵树,那 ...
- 实现哈夫曼编码(C语言)
编译环境:Dev-C++ 实现哈夫曼编码的贪心算法实现,并分析哈夫曼编码的算法复杂度. 哈夫曼编码贪心算法的原理如下: 该题目求最小编码长度,即求最优解的问题,可分成几个步骤,一般来说, 每个步骤的最 ...
- 算法科普:有趣的霍夫曼编码
前言 霍夫曼编码 ( Huffman coding ) 是一种可变长的前缀码.霍夫曼编码使用的算法是 David A. Huffman 还是在MIT 的学生时提出的,并且在 1952 年发表了名为&l ...
- 树的企业应用-哈夫曼编码树-有趣的数据压缩算法
树的企业应用-哈夫曼编码树-有趣的数据压缩算法 哈夫曼编码 描述 张三去李四家里,但 李四是一个女生,所以张三找李四去上海迪尼斯玩 - 亚历山大.张三去伊丽莎白.李四家里,但 伊丽莎白.李四是一个女生 ...
- 哈夫曼编码压缩率计算_程序员的算法课(8)-贪心算法:理解霍夫曼编码
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/m0_37609579/article/ ...
- 贪心算法-03哈夫曼编码问题
哈夫曼编码 简介 哈夫曼编码是一种字符编码方式,可以对指定的字符集进行数据压缩,压缩率在20%到90%. 问题描述 现在有一个包含5个字符{A,B,C,D,E},各个字符的出现频率依次为{0.35, ...
- 贪心算法 - 哈夫曼编码 Huffman
转载地址 : http://blog.csdn.net/xuefeng0707/article/details/7844834 哈夫曼编码: 一种字符编码方式,常用于数据文件压缩.压缩率通常在2 ...
- 贪心算法之用优先队列(priority_queue)实现哈夫曼编码问题
1.问题 参考我的博客:贪心算法之哈夫曼编码问题 2.优先队列知识复习 参考我的博客: C++之STL之priority_queue 3.代码实现 #include <iostream> ...
- 贪心算法之最小堆实现霍夫曼编码
贪心算法之最小堆实现霍夫曼编码 实现之前需要学习的地方: 如果你不了解堆.堆的插入.堆的删除,可以先看下我前面几篇博客 http://blog.csdn.net/u011068702/article/ ...
最新文章
- 7-24 约分最简分式 (C语言)
- hellowolrd 的系统调用
- Servlet WEB过滤器
- 1.在VS2010中文版中开发WP7程序
- Michael-Scott非阻塞队列(lock-free)算法的C实现
- Linux 基础I/O :文件描述符,重定向,文件系统,软链接和硬链接,动态库和静态库
- 算法题目中常见的几种输入小点-gets,cin,scanf,getline,sstream
- C++this指针的用途
- navicat无法连接远程mysql数据库_navicat无法远程连接mysql的解决方法
- python中factor函数_Python入门-函数
- padding三个值含义
- Pandas系列(八)字符串处理
- Java开发中,接口参数校验
- 对接融云记录几点问题
- html grid插件,grid.html
- 中北计算机组成原理期末,中北大学《计算机组成原理》选择题和填空题试题大集合(含答案).pdf...
- Pytorch 深度学习入门与实践 第二章 pytorch快速入门 (1)
- 微处理器常见问题及解答
- 我国逸管家中小企业融资难现状及分析(含开题报告、实践报告)(20180404105041)
- 面试时想拿 13K,HR 说你只值 8K,该怎么回答?
热门文章
- 全世界最全牛人博客,你可以学习到太多!
- java怎么实现读取文件_Java读取文件的简单实现方法
- Objective-C 函数
- python查找excel中内容_Excel查找数据
- 计算机无法预览文件,win10系统百度网盘文件无法预览的解决方法
- .net C#实现图像对比
- netsetman使用教程_人性化的IP切换工具—NetSetMan
- NetSetMan NetSetMan IP快速切换
- sprintf函数的用法linux,Linux 常用函数——sprintf函数
- 【C语言程序】鸡兔同笼问题