【POJ1521】【HDU1053】Entropy 哈夫曼(Huffman)编码

#include <stdio.h>
int main()
{
	puts("转载请注明出处谢谢");
	puts("http://blog.csdn.net/vmurder/article/details/43020921");
}

题意:

输出字符串的长度*8、huffman编码长度、两者比值。

题解:

huffman编码:

我们发现对于一个字符串,如果我们把它变成01串,比如ABCDE

那么我们需要

A : 000

B : 001

C : 010

D : 100

E : 101

来表示每一个字符,然后识别的时候就是每三个一识别。

这种编码叫定长编码。

显然对于一个串,它的定长编码长度是串长*定长。

但是其实它可以更短。

如果我们想要识别一个串,就需要所有字符的编码都不为其它编码的前缀,这样才可以成功解码。

而此时我们可以根据出现频率来构造huffman编码,以达到最优解。

构造方法可以见于黑书P245,毕竟它还是很水的,随便看看就能明白。

下面是我要讲的方法:

这种编码最后可以构成一颗二叉树,每个叶子节点都是一种字符,而它的变长编码(Huffman)就是从root到这个节点经过的边的序号序列,而左儿子边序号标0,右儿子边序号标1。

建树方法:先把所有字符按照出现次数作为关键字排序,然后给最小的两个赋一个父亲,然后把这两个叶子节点弹出优先队列,把父亲插入进去,父亲的关键字是儿子的size之和。

最后只剩下一个节点的时候停止。

证明在黑书上有,自己去翻吧,感性的思考一下就是每个点都有深度,然后∑深度*size=ans,

我们需要让size大的深度尽量小。

呃,虽然上面的证明显然是在chedan,但是,,并没有但是。

代码:

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 1000
using namespace std;
char s[N];
int cnt[N];
priority_queue<int>q;
int ans,len;
int main()
{
	freopen("test.in","r",stdin);
	int i,j,k;
	while(scanf("%s",s)!=EOF)
	{
		while(!q.empty())q.pop();
		len=strlen(s),ans=0;
		if(len==3&&s[0]=='E'&&s[1]=='N'&&s[2]=='D')return 0;
		memset(cnt,0,sizeof cnt);
		for(i=0;s[i];i++)cnt[s[i]]++;
		for(i=0;i<N;i++)if(cnt[i])q.push(-cnt[i]);
		for(;;)
		{
			i=q.top(),q.pop();
			if(q.empty())break;
			j=q.top(),q.pop();
			ans-=(i+j);
			q.push(i+j);
		}
		if(!ans)ans=len;
		printf("%d %d %.1lf\n",len*8,ans,(double)len*8/(double)ans);
	}
	return 0;
}
时间: 2024-11-10 11:32:56

【POJ1521】【HDU1053】Entropy 哈夫曼(Huffman)编码的相关文章

赫夫曼树编码

在一般的数据结构的书中,树的那章后面,著者一般都会介绍一下哈夫曼(HUFFMAN) 树和哈夫曼编码.哈夫曼编码是哈夫曼树的一个应用.哈夫曼编码应用广泛,如 JPEG中就应用了哈夫曼编码. 首先介绍什么是哈夫曼树.哈夫曼树又称最优二叉树, 是一种带权路径长度最短的二叉树.所谓树的带权路径长度,就是树中所有的叶结点 的权值乘上其到根结点的 路径长度(若根结点为0层,叶结点到根结点的路径长度 为叶结点的层数).树的带权路径长度记为WPL= (W1*L1+W2*L2+W3*L3+...+Wn*Ln) ,

赫夫曼树编码的表示与实现--自己写数据结构

头文件huffman.h #ifndef _HUFFMAN_H_ #define _HUFFMAN_H_ #define MAX_WEIGHT 10000 typedef struct _HTNode { int weight; int parent,lchild,rchild; char data; }HTNode,*pHTNode; typedef char** huffmancode; void select_min_weight(HTNode* btree,int mn,int* s1,

20172303 2018-2019-1《程序设计与数据结构》哈夫曼树编码与解码

20172303 2018-2019-1<程序设计与数据结构>哈夫曼树编码与解码 哈夫曼树简介 定义:给定n个权值作为n个叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree).哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近. 带权路径长度(Weighted Path Length of Tree,简记为WPL) 结点的权:在一些应用中,赋予树中结点的一个有某种意义的实数. 结点的带权路径长度:结点到树根之间的路径长度与

构造最优二叉树-赫夫曼(Huffman)树算法

一.基本概念 1.赫夫曼(Huffman)树又称最优二叉树或最优搜索树,是一种带权路径长度最短的二叉树.在许多应用中,常常赋给树中结点一个有某种意义的实数,称此实数为该结点的权.从树根结点到该结点之间的路径长度与该结点上权的乘积称为结点的带权路径长度(WPL),树中所有叶子结点的带权路径长度之和称为该树的带权路径长度,通常记为: 2.两结点间的路径:从一结点到另一结点所经过的结点序列;路径长度:从根结点到相应结点路径上的分支数目;树的路径长度:从根到每一结点的路径长度之和. 3.深度为k,结点数

哈夫曼 (Huffman) 树的动画演示

 哈夫曼 (Huffman) 树的动画演示: http://people.cs.pitt.edu/~kirk/cs1501/animations/Huffman.html 此网站中亦有诸多其它算法的动画演示,可供学习算法或是数据结构相关内容时参考.

哈夫曼(Huffman)树与哈夫曼编码

声明:原创作品,转载时请注明文章来自SAP师太技术博客:www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将追究法律责任!原文链接:http://www.cnblogs.com/jiangzhengjun/p/4289610.html 哈夫曼树又称最优二叉树,是一种带权路径长最短的树.树的路径长度是从树根到每一个叶子之间的路径长度之和.节点的带树路径长度为从该节点到树根之间的路径长度与该节点权(比如字符在某串中的使用频率)的乘积. 比如有一串字符串如

C++哈夫曼树编码和译码的实现

一.背景介绍: 给定n个权值作为n个叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree).哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近. 二.实现步骤: 1.构造一棵哈夫曼树 2.根据创建好的哈夫曼树创建一张哈夫曼编码表 3.输入一串哈夫曼序列,输出原始字符 三.设计思想: 1.首先要构造一棵哈夫曼树,哈夫曼树的结点结构包括权值,双亲,左右孩子:假如由n个字符来构造一棵哈夫曼树,则共有结点2n-1个:在构造前,先初始化

文件压缩——哈夫曼树编码(一)

何谓哈夫曼树?-- 百度百科:给定n个权值作为n个叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree).哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近. 哈夫曼树的应用?-- 哈夫曼编码 与 哈夫曼译码. 哈夫曼树为基础的项目?-- 文件压缩. 文件压缩分两种:1.有损压缩.2.无损压缩. 哈夫曼树为核心算法的压缩方式是无损压缩. 其实我们windows常用的zip类型的压缩包底层,哈夫曼树就是核心算法之一(当然不全是)

看数据结构写代码(32) 赫夫曼树编码以及译码

杂谈:最近有点慵懒,不好不好.好几天都没写代码,原本准备上星期完结 树 这一章节的.现在 又耽误了.哎.要抓紧时间啊. 下面直接上代码: 可以到我的网盘下载源代码,或者 直接拷贝下面的源代码 运行 网盘地址:点击打开链接 // HuffmanTree.cpp : 定义控制台应用程序的入口点. //哈弗曼编码,译码 #include "stdafx.h" #include <stdlib.h> #include <cstring> enum E_State { E