霍夫曼编码(贪心)

目录

1.什么叫霍夫曼编码

2.如何手工运算得到霍夫曼编码

3.完整源码

(1)只输出权值

(2)输出树形


1.什么叫霍夫曼编码

霍夫曼编码(英语:Huffman Coding),又译为哈夫曼编码、赫夫曼编码,是一种用于无损数据压缩的熵编码(权编码)算法。由大卫·霍夫曼在1952年发明。

在计算机数据处理中,霍夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编码表是通过一种评估来源符号出现机率的方法得到的,出现机率高的字母使用较短的编码,反之出现机率低的则使用较长的编码,这便使编码之后的字符串的平均长度、期望值降低,从而达到无损压缩数据的目的。

例如,在英文中,e的出现机率最高,而z的出现概率则最低。当利用霍夫曼编码对一篇英文进行压缩时,e极有可能用一个比特来表示,而z则可能花去25个比特(不是26)。用普通的表示方法时,每个英文字母均占用一个字节,即8个比特。二者相比,e使用了一般编码的1/8的长度,z则使用了3倍多。倘若我们能实现对于英文中各个字母出现概率的较准确的估算,就可以大幅度提高无损压缩的比例。

霍夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数)。树的路径长度是从树根到每一结点的路径长度之和。

 

霍夫曼编码(贪心)_第1张图片 


2.如何手工运算得到霍夫曼编码

前缀码:编码的任意前缀不是其他编码 

解码结果唯一,编码方式可行

问题:如何求得编码后二进制串总长最短的前缀码?

优先处理低频字符

⚫ 将字符频数从小到大排序 =< , , … , > ( ≤ ≤ ⋯ ≤ )

⚫ 选择两个最小的频数, ,合并为 ′ = +  

霍夫曼编码(贪心)_第2张图片 霍夫曼编码(贪心)_第3张图片

霍夫曼编码(贪心)_第4张图片 霍夫曼编码(贪心)_第5张图片


⚫在 ′ =< ′, , … , > 中重复选择合并过程 

霍夫曼编码(贪心)_第6张图片霍夫曼编码(贪心)_第7张图片

霍夫曼编码(贪心)_第8张图片 霍夫曼编码(贪心)_第9张图片


霍夫曼编码(贪心)_第10张图片 霍夫曼编码(贪心)_第11张图片

霍夫曼编码(贪心)_第12张图片 霍夫曼编码(贪心)_第13张图片


霍夫曼编码(贪心)_第14张图片 霍夫曼编码(贪心)_第15张图片

霍夫曼编码(贪心)_第16张图片 霍夫曼编码(贪心)_第17张图片


霍夫曼编码(贪心)_第18张图片 霍夫曼编码(贪心)_第19张图片

霍夫曼编码(贪心)_第20张图片 霍夫曼编码(贪心)_第21张图片


霍夫曼编码(贪心)_第22张图片 


3.完整源码

(1)只输出权值

#include
#include
#include
using namespace std;
priority_queue,greater > q;
int main()
{
	int n;
	cin>>n;
	int x;
	for(int i=0;i>x;
		q.push(x);
	}
	while(q.size()>1)
	{
		int x,y;
		x=q.top();
		q.pop();
		y=q.top();
		q.pop();
		q.push(x+y);
	}
	cout<

 (2)输出树形

#include
#include
#include
#include
#include
#include 
using namespace std;
struct node//结构体 
{
	int sum;//该点权值 
	node *left;
	node *right;
};
node an[10010];
bool cmp1(node a,node b){return a.sumsum>b->sum;
		}
};
priority_queue,cmp > q;//优先队列  递增排序 
int main()
{
	int n;
	cin>>n;//建立有n个点的Huffman树 
	int x;
//(这里如果直接输入值插入队列里面有点bug,得按规律输入,改不出来了QAQ,
// 只好先输入一组数据排序后再插入队列里面)
	for(int i=0;i>an[i].sum;
		an[i].left=NULL;
		an[i].right=NULL;
	}
	sort(an,an+n,cmp1);
	for(int i=0;i1)//按权值从小到大建树 
	{
		node *a;//取两个最小点合并 
		a=(node*)malloc(sizeof(node));
		a->sum=0;
		a->left=q.top();
		a->sum+=q.top()->sum;
		q.pop();
		a->right=q.top();
		a->sum+=q.top()->sum;
		q.pop(); 
		
		q.push(a);//把新点放入优先队列 
		//cout<<"push增加成功"< q2;
	queue q3;
	q2.push(gen);
	cout<<"该huffman树形大概为:"<0)
	{
		if(q2.front()==NULL)
		{
			q2.pop();
			continue;
		}
		q3.push(q2.front()->left);
		q3.push(q2.front()->right);
		cout<sum<<" ";
		q2.pop();
		if(q2.size()==0)
		{
			while(q3.size()>0)
			{
				q2.push(q3.front());
				q3.pop();
			}
			cout<sum<

你可能感兴趣的:(算法,算法,贪心算法,蓝桥杯,c++,霍夫曼树)