Haffman编码

时间限制:1000 ms  |  内存限制:65535 KB
难度:3
 
描述

哈弗曼编码大家一定很熟悉吧(不熟悉也没关系,自己查去。。。)。现在给你一串字符以及它们所对应的权值,让你构造哈弗曼树,从而确定每个字符的哈弗曼编码。当然,这里有一些小规定:

1.规定哈弗曼树的左子树编码为0,右子树编码为1;

2.若两个字符权值相同,则ASCII码值小的字符为左孩子,大的为右孩子;

3.创建的新节点所代表的字符与它的左孩子的字符相同;

4.所有字符为ASCII码表上32-96之间的字符(即“ ”到“`”之间的字符)。

 
输入
输入包含多组数据(不超过100组) 每组数据第一行一个整数n,表示字符个数。接下来n行,每行有一个字符ch和一个整数weight,表示字符ch所对应的权值,中间用空格隔开。 输入数据保证每组测试数据的字符不会重复。
输出
对于每组测试数据,按照输入顺序输出相应的字符以及它们的哈弗曼编码结果,具体格式见样例。
样例输入
3
a 10
b 5
c 8
4
a 1
b 1
c 1
d 1
样例输出
a:0
b:10
c:11
a:00
b:01
c:10
d:11
题解:让求一颗哈夫曼树,哈夫曼树是先找到最小的两个建一个根节点,这个根节点的权值为两个小的权值和;
加入这个新节点,重新找;用优先队列实现;其根节点即为元素在树中的位置;
代码:
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int INF=0x3f3f3f3f;
#define mem(x,y) memset(x,y,sizeof(x))
#define SI(x) scanf("%d",&x)
#define PI(x) printf("%d",x)
typedef long long LL;
string ans[];
char c[];
struct Node{
char c;
int v;
Node *l,*r;
Node(){
l=r=NULL;
}
Node(char ch,int vv,Node *ll=NULL,Node *rr=NULL){
c=ch;v=vv;l=ll;r=rr;
}
bool operator < (const Node &b) const{
if(v!=b.v)return v>b.v;
else return c>b.c;
}
};
Node e[];
void dfs(Node *now,string s){
if(now->l==NULL&&now->r==NULL){
ans[int(now->c)]=s;return;
}
if(now->l!=NULL)dfs(now->l,s+'');
if(now->r!=NULL)dfs(now->r,s+'');
return ;
}
int main(){
int N,v;
//char s[2];
while(~SI(N)){
if(N==)continue;
for(int i=;i<;i++)e[i].l=e[i].r=NULL;
priority_queue<Node>Q;
getchar();
for(int i=;i<N;i++){
scanf("%c %d",&c[i],&v);getchar();//这里不这样输入就错了
//c[i]=s[0];
Q.push(Node(c[i],v));
}
int tp=;
while(Q.size()>){
e[tp++]=Q.top();
Q.pop();
e[tp++]=Q.top();
Q.pop();
Q.push(Node(e[tp-].c,e[tp-].v+e[tp-].v,&e[tp-],&e[tp-]));
//Node(e[tp-2].c这样插是为了当和等于下一个的v的时候排在前边;
//为什么要再开一个数组e:为了保持队列里面元素的l,r对应关系;
}
Node ss;
ss=Q.top();
//printf("%c %d\n",ss.c,ss.v);
dfs(&ss,"");
//printf("****");
for(int i=;i<N;i++){
//printf("%c:%s\n",c[i],ans[int(c[i])].c_str());
cout<<c[i]<<":"<<ans[int(c[i])]<<endl;
}
}
return ;
}

数据结构课后又写了下:优先队列那点要用仿函数写;

代码:

#include "handsomecui.h"
#include<queue>
#include<vector>
struct Node{
int v;
char c;
Node *l, *r;
Node(){
l = NULL;
r = NULL;
}
void init(int v, char c, Node *l = NULL, Node *r = NULL){
this->v = v;
this->c = c;
this->l = l;
this->r = r;
}
// bool operator < (const Node *a) const{
// return v > a->v;//这里的排序有问题
// }
};
struct cmp{
bool operator() (const Node *a, const Node *b) const{
if(a->v != b->v)
return (a->v) > (b->v);
else
return a->c > b->c;
}
};
priority_queue<Node*, vector<Node*>, cmp>Q;
string ans[];
void dfs(Node *root, string s){
if(root->l == NULL && root->r == NULL){
ans[root->c] = s;
return;
}
if(root->l != NULL){
dfs(root->l, s + '');
}
if(root->r != NULL){
dfs(root->r, s + '');
}
}
char s[];
void print(char c){
PI(c, ":");
PI(ans[c] , "\n");
}
int main(){
int n;
int v;
while(~scanf("%d", &n)){
if(n == )
continue;
getchar();
while(!Q.empty())
Q.pop();
Node *a, *b, *c;
for(int i = ; i < n; i++){
a = new Node();
scanf("%c%d", &s[i], &v);
getchar();
a->init(v, s[i]);
Q.push(a);
}
while(Q.size() > ){
a = Q.top();
Q.pop();
b = Q.top();
Q.pop();
c = new Node();
c->init(a->v + b->v, a->c, a, b);
Q.push(c);
}
dfs(Q.top(), "");
for_each(s, s + n, print);
}
return ;
}

Haffman编码(haffman树)的更多相关文章

  1. ACM Haffman编码

    Haffman编码 时间限制:1000 ms  |  内存限制:65535 KB 难度:3   描述 哈弗曼编码大家一定很熟悉吧(不熟悉也没关系,自己查去...).现在给你一串字符以及它们所对应的权值 ...

  2. java实现Haffman编码

    1.先创建一个树节点类(泛型类),为了方便使用集合的排序方法,泛型类要实现泛型接口Comparable,代码如下 package com.hjp.huffman; /** * Created by J ...

  3. Haffman编码

    Huffman树又称为最优树,是一种带权路径最短的树. 一.带权路径 在一棵树中我们把一个节点到另一个节点之间的通路叫做路径,在路径中每经过一个节点路径的长度就加一.如果对一个节点附上权值,则该节点的 ...

  4. 【算法】Prüfer编码 —— HNOI2004树的计数

    的确,如果不知道这个编码的话的确是一脸懵逼.在这里放一篇认为讲的很详细的 BLOG,有关于编码的方式 & 扩展在里面都有所提及. 欢迎点此进入 --> 大佬的博客 在这里主要想推导一下最 ...

  5. 4.15 省选模拟赛 编码 trie树 前缀和优化建图 2-sat

    好题 np. 对于20分 显然可以爆搜. 对于50分 可以发现每个字符串上的问号要么是0,要么是1.考虑枚举一个字符串当前是0还是1 这会和其他字符串产生矛盾. 所以容易 发现这是一个2-sat问题. ...

  6. 文件压缩小项目haffman压缩

    文件压缩的原理: 文件压缩总体可以分为有损压缩和无损压缩两类,有损压缩是指对mp3等格式的文件,忽略一些无关紧要的信息,只保留一些关键的信息,但并不因此影响用户对于这些mp3格式文件的体验度,无损压缩 ...

  7. deflate树与deflate编码

    关于deflate树,能搜到的资料非常少,这个概念来自gzip的压缩算法,是由huffman树转变过来的.这里简单记录下deflate树的生成过程以及deflate编码. 假设以5 8 9 10 14 ...

  8. 【转】ACM 2567 -- 树的Prufer编码

    本文介绍北京大学ACM网站2567号题目的解法.介绍部分基本翻译自网站上的题目介绍. 题目介绍:    给定一棵各节点编号为整数1,2,3...n的树(例如,无环连通图),其Prufer编码(Pruf ...

  9. 树的计数 Prüfer编码与Cayley公式 学习笔记

    最近学习了Prüfer编码与Cayley公式,这两个强力的工具一般用于解决树的计数问题.现在博主只能学到浅层的内容,只会用不会证明. 推荐博客:https://blog.csdn.net/moreja ...

随机推荐

  1. hibernate 非xml实体类配置方法!

    hibernate 非xml实体类配置方法! 这个是hibernate.cfg.xml配置文件 <?xml version='1.0' encoding='UTF-8'?> <!DO ...

  2. Ubuntu12.04 Jdk1.7 Tomct7.0部署配置

    jdk1.7 下载 http://download.oracle.com/otn-pub/java/jdk/7u67-b01/jdk-7u67-linux-x64.tar.gz?AuthParam=1 ...

  3. 关于xxx.h file not found 的问题

    在引用第三方库的时候,经常会遇到xxx.h file not found的问题. 首先,我们要知道在引用第三方的时候,我们使用的第三方的库的类型. .a静态库 使用方式:#import "x ...

  4. 浅析StackTrace【转】

    我们在学习函数调用时,都知道每个函数都拥有自己的栈空间.一个函数被调用时,就创建一个新的栈空间.那么通过函数的嵌套调用最后就形成了一个函数调用堆栈.在c#中,使用StackTrace记录这个堆栈.你可 ...

  5. 单调旋转数组的TopK问题

    问题描述:输入一个单调旋转后的数组,求该数组中的第k小的元素. 分析:很多人看到这个题目会有点懵,可能读者不知道什么是旋转数组,我先解释下两个概念, 旋转数组的定义:把一个数组的前几项元素移动到数组的 ...

  6. 【最大流,二分图匹配】【hdu2063】【过山车】

    题意:裸的求二分图匹配 建立一个源点 连向一边所有的点 容量为1; 另外一边点都连向汇点  容量为1; 二分图的边容量也为1 源点汇点求一遍最大流即可 #include <cstdio> ...

  7. flex布局的使用,纪念第一次开发手机网站

    一直专注于PC网站的开发,不曾接触手机网站,于今日机缘巧合也是公司业务需要,并在之前学习过flex的布局,于是一并实践.碰到的问题还是很多的,主要是谈谈flex布局. flex布局是css3里的内容, ...

  8. SQL Server 已提交读快照 测试

    1. 打开数据库 已提交读快照 选项 2. 数据库 已提交读快照 模式下的测试 a) 测试表 Test b) 开启事务1,更新数据C2 = '200'(未提交) BEGIN TRAN ' WHERE ...

  9. MVC 使用PageList进行分页

    1.新建MVC项目 2.在Web项目下添加PagedList nuget 命令 :install-package pagedlist.mvc 在安装完成之后,会在Content下添加PagedList ...

  10. zookeeper集群挂了,提示

    Hadoop集群意外关机后,zookeeper服务出现停止状态, 日志错误提示如下: java.io.IOException: Transaction log: //log.260010d366 ha ...