哈夫曼编码

Huffman编码(Huffman树)

橙三吉。 提交于 2020-03-09 20:03:22
【0】README 0.1) 本文总结于 数据结构与算法分析, 源代码均为原创, 旨在 理解 “Huffman编码(Huffman树)” 的idea 并用源代码加以实现; 0.2) Huffman树的构建算法属于 贪婪算法 , 贪婪算法的基础知识参见:   http://blog.csdn.net/pacosonswjtu/article/details/50071159 【1】Huffman 编码 1.1)贪婪算法的第二个应用: 文件压缩; 1.1.1)标准的 ASCII字符集: 它由大约100个 可打印字符组成,为了把这些字符区分开, 需要 |log100|(不小于等于log100) = 7个 比特; 1.1.2)看个荔枝:(使用一个标准编码方案) 设一个文件, 它只包含字符 a, e, i, s, t, 加上一些空格和 newline(换行)。 进一步设该文件有10个a、15个e、12个i、3个s、4个t、13个空格以及一个 newline, 如图10-8所示, 这个文件需要174个bits 来表示,因为有58个字符,每个字符3个bits; 1.2)现实中的事实: 文件可能相当大。 许多大文件是某个程序的输出数据,而在使用频率最大和最小之间的字符间通常存在很大的差别; 1.2.1)出现的问题: 是否有可能提供一种更好的编码降低总的所需bits数量 2.2)解决方法:

数据结构实验之二叉树六:哈夫曼编码

痞子三分冷 提交于 2020-02-22 12:31:04
Description 字符的编码方式有多种,除了大家熟悉的ASCII编码,哈夫曼编码(Huffman Coding)也是一种编码方式,它是可变字长编码。该方法完全依据字符出现概率来构造出平均长度最短的编码,称之为最优编码。哈夫曼编码常被用于数据文件压缩中,其压缩率通常在20%~90%之间。你的任务是对从键盘输入的一个字符串求出它的ASCII编码长度和哈夫曼编码长度的比值。 Input 输入数据有多组,每组数据一行,表示要编码的字符串。 Output 对应字符的ASCII编码长度la,huffman编码长度lh和la/lh的值(保留一位小数),数据之间以空格间隔。 Sample Input AAAAABCD THE_CAT_IN_THE_HAT Output 64 13 4.9 144 51 2.8 Hint #include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; bool cmp(int a,int b) { return a>b; } int main() { char str[1000]; while(scanf("%s",str)!=EOF) { char s[1000]; int sn[1000]={0}; int len

java 哈夫曼编码

蓝咒 提交于 2020-02-12 16:09:24
//哈夫曼树类 public class HaffmanTree { //最大权值 static final int MAXVALUE=1000; int nodeNum ; //叶子结点个数 public HaffmanTree(int n) { this.nodeNum = n; } //构造哈夫曼树算法 public void haffman(int[] weight,HaffNode[] nodes)//权值数组,所有节点数组 { int n = this.nodeNum; //m1,m2,表示最小的两个权值,x1,x2,表示最小两个权值对应的编号,m1表示最小,m2表示次小 int m1,m2,x1,x2; //初始化所有的结点,对应有n个叶子结点的哈夫曼树,有2n-1个结点。 for(int i=0;i < 2*n-1;i++) { HaffNode temp = new HaffNode(); //初始化n个叶子结点,就是输入的节点。0、1、2、3是叶子节点也是输入的节点 if(i < n) { temp.weight = weight[i]; } else { temp.weight = 0; } temp.parent = 0; temp.flag = 0; temp.leftChild = -1; temp.rightChild = -1; nodes[i] =

哈夫曼树与哈夫曼编码

怎甘沉沦 提交于 2020-02-12 13:03:57
哈夫曼树与哈夫曼编码 术语 : i)路径和路径长度 在一棵树中,从一个结点往下可以达到的孩子或孙子结点之间的通路,称为路径。 路径中分支的数目称为路径长度。若规定根结点的层数为1,则从根结点到第L层结点的路径长度为L-1。 ii)结点的权及带权路径长度 若对树中的每个结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。 结点的带权路径长度为:从根结点到该结点之间的路径长度与该结点的权的乘积。 iii)树的带权路径长度 树的带权路径长度:所有 叶子结点 的带权路径长度之和,记为WPL。 先了解一下哈夫曼树,之后再构造一棵哈夫曼树,最后分析下哈夫曼树的原理。 1)哈夫曼树 哈夫曼树是这样定义的:给定n个带权值的节点,作为叶子节点,构造一颗二叉树,使树的带权路径长度达到最小,这时候的二叉树就是哈夫曼树,也叫最优二叉树。 哈夫曼树具有如下性质: 1)带权路径长度最短 2)权值较大的结点离根较近 2)构造哈夫曼树 构造哈夫曼树的步骤如下: 假设有n个权值,则构造出的哈夫曼树有n个叶子结点。 n个权值分别设为 w1、w2、…、wn,则哈夫曼树的构造规则为: 1) 将w1、w2、…,wn看成是有n 棵树的森林(每棵树仅有一个结点); 2) 在森林中选出两个根结点的权值最小的树合并,作为一棵新树的左、右子树, 且新树的根结点权值为其左、右子树根结点权值之和 3)从森林中删除选取的两棵树

哈夫曼编码(30分)

…衆ロ難τιáo~ 提交于 2020-02-11 01:51:30
给定一段文字,如果我们统计出字母出现的频率,是可以根据哈夫曼算法给出一套编码,使得用此编码压缩原文可以得到最短的编码总长。然而哈夫曼编码并不是唯一的。例如对字符串"aaaxuaxz",容易得到字母 'a'、'x'、'u'、'z' 的出现频率对应为 4、2、1、1。我们可以设计编码 {'a'=0, 'x'=10, 'u'=110, 'z'=111},也可以用另一套 {'a'=1, 'x'=01, 'u'=001, 'z'=000},还可以用 {'a'=0, 'x'=11, 'u'=100, 'z'=101},三套编码都可以把原文压缩到 14 个字节。但是 {'a'=0, 'x'=01, 'u'=011, 'z'=001} 就不是哈夫曼编码,因为用这套编码压缩得到 00001011001001 后,解码的结果不唯一,"aaaxuaxz" 和 "aazuaxax" 都可以对应解码的结果。本题就请你判断任一套编码是否哈夫曼编码。 输入格式: 首先第一行给出一个正整数 N(2≤N≤63),随后第二行给出 N 个不重复的字符及其出现频率,格式如下: c[1] f[1] c[2] f[2] ... c[N] f[N] 其中 c[i] 是集合{'0' - '9', 'a' - 'z', 'A' - 'Z', '_'}中的字符; f[i] 是 c[i] 的出现频率,为不超过 1000 的整数

算法作业三-哈夫曼编码

狂风中的少年 提交于 2020-02-08 05:51:51
实验三 哈夫曼编码 问题描述与实验目的: 给定n个字母(或字)在文档中出现的频率序列X=<x1,x2,…,xn>,求出这n个字母的Huffman编码。为方便起见,以下将频率用字母出现的次数(或称权值)w1,w2,…,wn代替。 输入 输入文件中的开始行上有一个整数T,(0<T<=20),表示有T组测试数据。 接下来是T行测试数据的描述,每组测试数据有2行。测试数据的第1行上是一个正整数n,(n<50),表示序列的长度。第2行是n个字母出现的权值序列w1,w2,…,wn,它们均为正整数,相邻的两个整数之间用空格隔开。 输入直到文件结束。 输出 对输入中的每组有n个权值的数据,应输出n+1行:先在一行上输出“Case #”,其中“#”是测试数据的组号(从1开始);接下来输出n行,其第1行到第n行上依次输出第i个字母出现的次数和相应的Huffman编码,格式如下: wi Huffman编码。 每组测试数据对应的输出最后结束时加一个空行,以便区分。 为保证Huffman编码的唯一性,在构造Huffman树的过程中,我们约定: 1.左儿子标记为0,右儿子标记为1; 2.左儿子的权值>=右儿子的权值; 3.相同权值w的两个字母x、y,先输入权值的字母x的Huffman编码长度不超过后输入权值的字母y的Huffman编码长度。 4.合并两个节点后新的权值应从右到左搜索、插入到相应的位置。 例如

哈夫曼树基本操作(暂无压缩文件功能版本)

限于喜欢 提交于 2020-01-15 07:34:53
# include "pch.h" # define _CRT_SECURE_NO_WARNINGS //避免strcpy()不能使用 # include <stdio.h> # include <iostream> # include <string.h> # include <iomanip> //需要控制格式 // 这个头文件是声明一些 “流操作符”的 //比较常用的有:setw(int);//设置显示宽度,left//right//设置左右对齐。 setprecision(int);//设置浮点数的精确度。 using namespace std ; using std :: strcpy ; typedef char * * HuffmanCode ; //哈夫曼编码存放的二维动态数组 typedef struct { int weight ; int parent , lchild , rchild ; } HTnode , * HuffmanTree ; typedef struct { char ch ; int weight ; } CharArray ; //1.选择权值最小的2个结点 void Select ( HTnode a [ ] , int n , int & s1 , int & s2 ) { //n个结点中找最小2个结点,s1最小,s2次小 for

哈夫曼编码的理解(Huffman Coding)

本秂侑毒 提交于 2020-01-14 09:57:35
哈夫曼编码(Huffman Coding),又称霍夫曼编码,是一种编码方式,可变字长编码(VLC)的一种。Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫做Huffman编码(有时也称为霍夫曼编码)。 哈夫曼编码,主要目的是根据使用频率来最大化节省字符(编码)的存储空间。 简易的理解就是,假如我有A,B,C,D,E五个字符,出现的频率(即权值)分别为5,4,3,2,1,那么我们第一步先取两个最小权值作为左右子树构造一个新树,即取1,2构成新树,其结点为1+2=3,如图: 虚线为新生成的结点,第二步再把新生成的权值为3的结点放到剩下的集合中,所以集合变成{5,4,3,3},再根据第二步,取最小的两个权值构成新树,如图: 再依次建立哈夫曼树,如下图: 其中各个权值替换对应的字符即为下图: 所以各字符对应的编码为:A->11,B->10,C->00,D->011,E->010 霍夫曼编码是一种无前缀编码。解码时不会混淆。其主要应用在数据压缩,加密解密等场合。 如果考虑到进一步节省存储空间,就应该将出现概率大(占比多)的字符用尽量少的0-1进行编码,也就是更靠近根(节点少),这也就是最优二叉树-哈夫曼树。 来源: https://www.cnblogs.com/linhaostudy/p/12190270

Huffman算法实现文件压缩解压

China☆狼群 提交于 2020-01-04 01:15:42
title: Huffman算法实现文件压缩解压 date: 2020-01-02 20:33:11 description: 基于Huffman编码算法实现文件压缩解压 原文网址 Huffman算法实现文件压缩解压 前言  哈夫曼编码是一种贪心算法和二叉树结合的字符编码方式,具有广泛的应用背景,最直观的是文件压缩。下面讲述如何用哈夫曼编解码实现文件的压缩和解压。 哈夫曼编码的概念  哈夫曼树又称作最优树,是一种带权路径长度最短的树,而通过哈夫曼树构造出的编码方式称作哈夫曼编码。 也就是说哈夫曼编码是一个通过哈夫曼树进行的一种编码,一般情况下,以字符 “0” 与 “1” 表示。编码的实现过程很简单,只要实现哈夫曼树,通过遍历哈夫曼树,这里我们从根节点开始向下遍历,如果下个节点是左孩子,则在字符串后面追加 “0”,如果为其右孩子,则在字符串后追加 “1”。结束条件为当前节点为叶子节点,得到的字符串就是叶子节点对应字符的编码。 哈夫曼编码用于文件压缩的原理  我们都知道根据人类使用文字对应的每个字符都是有特定的频率的。比如说英文,一般来说字母a或者e的使用频率很高。如果我们能给出现频率最高的字符很短的编码,出现最少的字符最长的编码,而且保证每个编码都不是任意一个编码的前缀码。为什么要保证这样呢?如果任意一个编码都不是其他编码的前缀码

【NOI2015】荷马史诗

Deadly 提交于 2019-12-25 00:44:42
   题目链接 https://www.luogu.org/problem/P2168    题目大意 是给定 n 个单词 的出现次数 wi ,求用 k 进制的前缀码转换后得到的最小总长度,以及在保证总长度最小时的最长串 si 的长度最短。   这题现在来看算是NOI里很简单的了(我竟然凹出来了w),但是据说当时这题可是难倒一大片。首先是因为这题题干太长不怎么容易看懂,另外可能是因为当时哈弗曼树还没有那么常见,几乎没人想到有哈弗曼树这么一个东西。   好,来看题。题目很明确,目标是要使编码之后的总长度最小,那么现在就要想着,怎样把出现次数多的编码长度尽可能的缩小。但是题目里有个限制:任意一个k进制编码都不是其它编码的前缀。这样一来,题目的做法就指向了哈弗曼树。    哈弗曼树与哈夫曼编码    这里简单重复一下 ——(证明过程引用自耿国华主编的《数据结构——C语言描述》)   哈夫曼树特性:从根结点到所有叶子结点的带权路径长度最短(就是权大的放靠近树根的地方)   做法:挑选序列里最小的2个点合并作为子节点,根节点的权值为他们的和,把根节点加入原序列,重复上述操作。   哈夫曼编码特性:1.它是前缀码。前缀码就是题目里给的那种,任何一个编码都不是其它编码的前 t 项。 证明:哈夫曼编码是根到叶子路径上的边的编码序列,也就是等价边序列,而由树的特点可知