1.题目描述:
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
-
输入包含多组数据(不超过100组)
2.算法思路:
首先本体很明显使用贪心的哈夫曼编码的算法即生成最优二叉树
本题还要输出哈夫曼编码的编码序列
所以说生成最有二叉树之后,我们还需要利用DFS遍历整棵树求出所有的点的编码
DFS+贪心
3.AC代码:
本体,本人没有用优先队列的STL来实现,我亲自用堆模拟量优先队列
并且强烈的给出题人一个建议,把数据量加上
#include"iostream"
#include"cstdio"
#include"cstring"
#define N 1001
using namespace std;
typedef struct node
{
char c;
int weight;
int left;
int right;
int code[N];
int codenum;
}point;
int n;
point queue[N];
int heapnum;
int heap[N];
int root; //追踪莫下标
int p[N];
void siftdown(int i)
{
int t;
while(i*2<=heapnum)
{
if(queue[heap[i]].weight>=queue[heap[i*2]].weight)
{
if(queue[heap[i]].weight==queue[heap[i*2]].weight)
{
if(queue[heap[i]].c<queue[heap[i*2]].c) t=i;
else t=i*2;
}
else t=i*2;
}
else t=i;
if(i*2+1<=heapnum&&queue[heap[i*2+1]].weight<=queue[heap[t]].weight)
{
if(queue[heap[i*2+1]].weight==queue[heap[t]].weight)
{
if(queue[heap[i*2+1]].c<queue[heap[t]].c) t=i*2+1;
}
else t=i*2+1;
}
if(i!=t)
{
int w=heap[i];
heap[i]=heap[t];
heap[t]=w;
i=t;
}
else break;
}
}
void dfs(int root,int num)
{
if(queue[root].left==0&&queue[root].right==0)
{
queue[root].codenum=num-1;
for(int i=1;i<=queue[root].codenum;i++)
{
queue[root].code[i]=p[i];
}
return ;
}
else
{
p[num]=0;
dfs(queue[root].left,num+1);
p[num]=1;
dfs(queue[root].right,num+1);
}
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
getchar();
memset(p,0,sizeof(p));
memset(queue,0,sizeof(queue));
for(int i=1;i<=n;i++)
{
scanf("%c",&queue[i].c);getchar();
scanf("%d",&queue[i].weight);getchar();
}
for(int i=1;i<=n;i++) heap[i]=i;
heapnum=root=n;
for(int i=heapnum/2;i>=1;i--) siftdown(i);
while(heapnum!=1)
{
int k=queue[heap[1]].weight;
root++;
queue[root].c=queue[heap[1]].c;
queue[root].left=heap[1];
if(heapnum==2)
{
k+=queue[heap[2]].weight;
queue[root].weight=k;
queue[root].right=heap[2];
heap[2]=root;
heap[1]=heap[heapnum];
heapnum--;
siftdown(1);
}
else
{
heap[1]=heap[heapnum];
heapnum--;
siftdown(1);
queue[root].right=heap[1];
k+=queue[heap[1]].weight;
queue[root].weight=k;
heap[1]=root;
siftdown(1);
}
}
dfs(root,1);
for(int i=1;i<=n;i++)
{
printf("%c:",queue[i].c);
for(int j=1;j<=queue[i].codenum;j++) printf("%d",queue[i].code[j]);
printf("\n");
}
}
return 0;
}