哈夫曼编码(贪心)
来源:互联网 发布:ie9浏览器mac官方下载 编辑:程序博客网 时间:2024/05/03 16:43
算法设计例题:哈夫曼编码(贪心)
memory limit: 32768KB time limit: 1000MS
accept: 4 submit: 8
Description
给定字符出现的频率,构造哈夫曼编码。
设定哈夫曼树左子树编码为0,右子树编码为1。
Input
输入的第一行为测试样例的个数T( T <= 100 ),接下来有T个测试样例。每个测试样例的第一行是一个整数n( n <= 65 ),表示有n个字符需要编码。接下来n行,每行为一个字符c和一个整数w,分别表示字符的标识以及该字符出现的频率。
Output
对应每个测试样例输出一行,格式为"Case #:",其中'#'表示第几个测试样例(从1开始计),接下来n行,格式为"c w x",其中c为字符标识,w为该字符的频率,x为该字符的哈夫曼编码,以读入的字符顺序依次输出。
Sample Input
1
6
a 45
b 13
c 12
d 16
e 9
f 5
Sample Output
Case 1:
a 45 0
b 13 101
c 12 100
d 16 111
e 9 1101
f 5 1100
源码:
#include<cstdio>
#include<cstdlib>
#include<cstring>
struct htnode
{
int weight;
int parent,lchild,rchild;
}ht[200];
char hc[100][100];
char C[100][2];
int w[100];
//选择两个parent为0,且weight最小的结点s1和s2
void select(int n,int &s1,int &s2)
{
int i,min;
for(i=1;i<=n;++i)
{
if(ht[i].parent==0)
{
min=i;
break;
}
}
for(i=1;i<=n;++i)
{
if(ht[i].parent==0)
{
if(ht[i].weight<ht[min].weight)
min=i;
}
}
s1=min;
for(i=1;i<=n;++i)
{
if(ht[i].parent==0 && i!=s1)
{
min=i;
break;
}
}
for(i=1;i<=n;++i)
{
if(ht[i].parent==0 && i!=s1)
{
if(ht[i].weight<ht[min].weight)
min=i;
}
}
s2=min;
}
//构造哈夫曼树ht,w存放已知的n个权值
void CrtHuffmanTree(int n)
{
int m,i,s1,s2;
m=2*n-1;
memset(ht,0,sizeof(ht));
for(i=1;i<=n;++i)
{
ht[i].weight=w[i];
}
for(i=n+1;i<=m;++i)
{
select(i-1,s1,s2);
ht[s1].parent=i;
ht[s2].parent=i;
ht[i].lchild=s1;
ht[i].rchild=s2;
ht[i].weight=ht[s1].weight+ht[s2].weight;
}
}
//从叶子结点到根,逆向求每个叶子结点对应的哈夫曼编码
void CrtHuffmanCode(int n)
{
char cd[100];
int a[100];
int i,start,p;
int c;
cd[n-1]='\0';
for(i=1;i<=n;++i)
{
a[i]=0;
start=n-1;
for(c=i,p=ht[i].parent;p!=0;c=p,p=ht[p].parent)
{
if(ht[p].lchild==c)
{
cd[--start]='0';
a[i]++;
}
else
{
cd[--start]='1';
a[i]++;
}
}
strcpy(hc[i],&cd[start]);
}
for(i=1;i<=n;++i)
{
printf("%s %d %s\n",C[i],w[i],hc[i]);
}
}
int main()
{
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
int T,cas=1;
scanf("%d",&T);
while(T--)
{
int i,n;
scanf("%d",&n);
for(i=1;i<=n;++i)
{
scanf("%s %d",C[i],&w[i]);
}
printf("Case %d:\n",cas++);
CrtHuffmanTree(n);
CrtHuffmanCode(n);
}
return 0;
}
-----------------
#include<cstdlib>
#include<cstring>
struct htnode
{
int weight;
int parent,lchild,rchild;
}ht[200];
char hc[100][100];
char C[100][2];
int w[100];
//选择两个parent为0,且weight最小的结点s1和s2
void select(int n,int &s1,int &s2)
{
int i,min;
for(i=1;i<=n;++i)
{
if(ht[i].parent==0)
{
min=i;
break;
}
}
for(i=1;i<=n;++i)
{
if(ht[i].parent==0)
{
if(ht[i].weight<ht[min].weight)
min=i;
}
}
s1=min;
for(i=1;i<=n;++i)
{
if(ht[i].parent==0 && i!=s1)
{
min=i;
break;
}
}
for(i=1;i<=n;++i)
{
if(ht[i].parent==0 && i!=s1)
{
if(ht[i].weight<ht[min].weight)
min=i;
}
}
s2=min;
}
//构造哈夫曼树ht,w存放已知的n个权值
void CrtHuffmanTree(int n)
{
int m,i,s1,s2;
m=2*n-1;
memset(ht,0,sizeof(ht));
for(i=1;i<=n;++i)
{
ht[i].weight=w[i];
}
for(i=n+1;i<=m;++i)
{
select(i-1,s1,s2);
ht[s1].parent=i;
ht[s2].parent=i;
ht[i].lchild=s1;
ht[i].rchild=s2;
ht[i].weight=ht[s1].weight+ht[s2].weight;
}
}
//从叶子结点到根,逆向求每个叶子结点对应的哈夫曼编码
void CrtHuffmanCode(int n)
{
char cd[100];
int a[100];
int i,start,p;
int c;
cd[n-1]='\0';
for(i=1;i<=n;++i)
{
a[i]=0;
start=n-1;
for(c=i,p=ht[i].parent;p!=0;c=p,p=ht[p].parent)
{
if(ht[p].lchild==c)
{
cd[--start]='0';
a[i]++;
}
else
{
cd[--start]='1';
a[i]++;
}
}
strcpy(hc[i],&cd[start]);
}
for(i=1;i<=n;++i)
{
printf("%s %d %s\n",C[i],w[i],hc[i]);
}
}
int main()
{
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
int T,cas=1;
scanf("%d",&T);
while(T--)
{
int i,n;
scanf("%d",&n);
for(i=1;i<=n;++i)
{
scanf("%s %d",C[i],&w[i]);
}
printf("Case %d:\n",cas++);
CrtHuffmanTree(n);
CrtHuffmanCode(n);
}
return 0;
}
-----------------
// 哈夫曼编码(算法)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char *HuffmanCode; //动态分配数组,存储哈夫曼编码
typedef struct
{
unsigned int weight; //用来存放各个结点的权值
unsigned int parent,LChild,RChild; //指向双亲、孩子结点的指针
} HTNode, *HuffmanTree; //动态分配数组,存储哈夫曼树
//选择两个parent为0,且weight最小的结点s1和s2
void Select(HuffmanTree *ht,int n,int *s1,int *s2)
{
int i,min;
for(i=1; i<=n; i++)
{
if((*ht)[i].parent==0)
{
min=i;
break;
}
}
for(i=1; i<=n; i++)
{
if((*ht)[i].parent==0)
{
if((*ht)[i].weight<(*ht)[min].weight)
min=i;
}
}
*s1=min;
for(i=1; i<=n; i++)
{
if((*ht)[i].parent==0 && i!=(*s1))
{
min=i;
break;
}
}
for(i=1; i<=n; i++)
{
if((*ht)[i].parent==0 && i!=(*s1))
{
if((*ht)[i].weight<(*ht)[min].weight) min=i;
}
}
*s2=min;
}
//构造哈夫曼树ht。w存放已知的n个权值
void CrtHuffmanTree(HuffmanTree *ht,int *w,int n)
{
int m,i,s1,s2;
m=2*n-1;
*ht=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
for(i=1; i<=n; i++) //1--n号存放叶子结点,初始化
{
(*ht)[i].weight=w[i];
(*ht)[i].LChild=0;
(*ht)[i].parent=0;
(*ht)[i].RChild=0;
}
for(i=n+1; i<=m; i++)
{
(*ht)[i].weight=0;
(*ht)[i].LChild=0;
(*ht)[i].parent=0;
(*ht)[i].RChild=0;
} //非叶子结点初始化
printf("\nHuffmanTree: \n");
for(i=n+1; i<=m; i++) //创建非叶子结点,建哈夫曼树
{ //在(*ht)[1]~(*ht)[i-1]的范围内选择两个parent为0
//且weight最小的结点,其序号分别赋值给s1、s2
Select(ht,i-1,&s1,&s2);
(*ht)[s1].parent=i;
(*ht)[s2].parent=i;
(*ht)[i].LChild=s1;
(*ht)[i].RChild=s2;
(*ht)[i].weight=(*ht)[s1].weight+(*ht)[s2].weight;
printf("%d (%d, %d)\n",(*ht)[i].weight,(*ht)[s1].weight,(*ht)[s2].weight);
}
printf("\n");
} //哈夫曼树建立完毕
//从叶子结点到根,逆向求每个叶子结点对应的哈夫曼编码
void CrtHuffmanCode(HuffmanTree *ht, HuffmanCode *hc, int n)
{
char *cd;
int i,start,p;
unsigned int c;
hc=(HuffmanCode *)malloc((n+1)*sizeof(char *)); //分配n个编码的头指针
cd=(char *)malloc(n*sizeof(char)); //分配求当前编码的工作空间
cd[n-1]='\0'; //从右向左逐位存放编码,首先存放编码结束符
for(i=1; i<=n; i++) //求n个叶子结点对应的哈夫曼编码
{
start=n-1; //初始化编码起始指针
for(c=i,p=(*ht)[i].parent; p!=0; c=p,p=(*ht)[p].parent) //从叶子到根结点求编码
if( (*ht)[p].LChild==c) cd[--start]='0'; //左分支标0
else cd[--start]='1'; //右分支标1
hc[i]=(char *)malloc((n-start)*sizeof(char)); //为第i个编码分配空间
strcpy(hc[i],&cd[start]);
}
free(cd);
for(i=1; i<=n; i++)
printf("HuffmanCode of %3d is %s\n",(*ht)[i].weight,hc[i]);
printf("\n");
}
void main()
{
HuffmanTree HT;
HuffmanCode HC;
int *w,i,n,wei,m;
printf("\nn = " );
scanf("%d",&n);
w=(int *)malloc((n+1)*sizeof(int));
printf("\ninput the %d element's weight:\n",n);
for(i=1; i<=n; i++)
{
printf("%d: ",i);
fflush(stdin);
scanf("%d",&wei);
w[i]=wei;
}
CrtHuffmanTree(&HT,w,n);
CrtHuffmanCode(&HT,&HC,n);
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char *HuffmanCode; //动态分配数组,存储哈夫曼编码
typedef struct
{
unsigned int weight; //用来存放各个结点的权值
unsigned int parent,LChild,RChild; //指向双亲、孩子结点的指针
} HTNode, *HuffmanTree; //动态分配数组,存储哈夫曼树
//选择两个parent为0,且weight最小的结点s1和s2
void Select(HuffmanTree *ht,int n,int *s1,int *s2)
{
int i,min;
for(i=1; i<=n; i++)
{
if((*ht)[i].parent==0)
{
min=i;
break;
}
}
for(i=1; i<=n; i++)
{
if((*ht)[i].parent==0)
{
if((*ht)[i].weight<(*ht)[min].weight)
min=i;
}
}
*s1=min;
for(i=1; i<=n; i++)
{
if((*ht)[i].parent==0 && i!=(*s1))
{
min=i;
break;
}
}
for(i=1; i<=n; i++)
{
if((*ht)[i].parent==0 && i!=(*s1))
{
if((*ht)[i].weight<(*ht)[min].weight) min=i;
}
}
*s2=min;
}
//构造哈夫曼树ht。w存放已知的n个权值
void CrtHuffmanTree(HuffmanTree *ht,int *w,int n)
{
int m,i,s1,s2;
m=2*n-1;
*ht=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
for(i=1; i<=n; i++) //1--n号存放叶子结点,初始化
{
(*ht)[i].weight=w[i];
(*ht)[i].LChild=0;
(*ht)[i].parent=0;
(*ht)[i].RChild=0;
}
for(i=n+1; i<=m; i++)
{
(*ht)[i].weight=0;
(*ht)[i].LChild=0;
(*ht)[i].parent=0;
(*ht)[i].RChild=0;
} //非叶子结点初始化
printf("\nHuffmanTree: \n");
for(i=n+1; i<=m; i++) //创建非叶子结点,建哈夫曼树
{ //在(*ht)[1]~(*ht)[i-1]的范围内选择两个parent为0
//且weight最小的结点,其序号分别赋值给s1、s2
Select(ht,i-1,&s1,&s2);
(*ht)[s1].parent=i;
(*ht)[s2].parent=i;
(*ht)[i].LChild=s1;
(*ht)[i].RChild=s2;
(*ht)[i].weight=(*ht)[s1].weight+(*ht)[s2].weight;
printf("%d (%d, %d)\n",(*ht)[i].weight,(*ht)[s1].weight,(*ht)[s2].weight);
}
printf("\n");
} //哈夫曼树建立完毕
//从叶子结点到根,逆向求每个叶子结点对应的哈夫曼编码
void CrtHuffmanCode(HuffmanTree *ht, HuffmanCode *hc, int n)
{
char *cd;
int i,start,p;
unsigned int c;
hc=(HuffmanCode *)malloc((n+1)*sizeof(char *)); //分配n个编码的头指针
cd=(char *)malloc(n*sizeof(char)); //分配求当前编码的工作空间
cd[n-1]='\0'; //从右向左逐位存放编码,首先存放编码结束符
for(i=1; i<=n; i++) //求n个叶子结点对应的哈夫曼编码
{
start=n-1; //初始化编码起始指针
for(c=i,p=(*ht)[i].parent; p!=0; c=p,p=(*ht)[p].parent) //从叶子到根结点求编码
if( (*ht)[p].LChild==c) cd[--start]='0'; //左分支标0
else cd[--start]='1'; //右分支标1
hc[i]=(char *)malloc((n-start)*sizeof(char)); //为第i个编码分配空间
strcpy(hc[i],&cd[start]);
}
free(cd);
for(i=1; i<=n; i++)
printf("HuffmanCode of %3d is %s\n",(*ht)[i].weight,hc[i]);
printf("\n");
}
void main()
{
HuffmanTree HT;
HuffmanCode HC;
int *w,i,n,wei,m;
printf("\nn = " );
scanf("%d",&n);
w=(int *)malloc((n+1)*sizeof(int));
printf("\ninput the %d element's weight:\n",n);
for(i=1; i<=n; i++)
{
printf("%d: ",i);
fflush(stdin);
scanf("%d",&wei);
w[i]=wei;
}
CrtHuffmanTree(&HT,w,n);
CrtHuffmanCode(&HT,&HC,n);
}
参考资料:http://coolshell.cn/articles/7459.html
- 哈夫曼编码(贪心)
- UVALive 2088 Entropy (贪心 + 哈夫曼编码)
- 贪心算法--哈夫曼编码(java实现 )
- poj3253Fence Repair(贪心,哈夫曼编码)
- NYOJ801-哈夫曼编码(贪心AC)
- 贪心算法实例(六):哈夫曼编码
- 贪心算法-(哈夫曼编码)HuffmanCode
- 经典贪心,哈夫曼编码。
- 贪心算法---哈夫曼编码
- 贪心算法-哈夫曼编码
- 哈夫曼编码--贪心算法
- 【贪心】哈夫曼编码&哈夫曼树
- Huffman 编码 (贪心)
- 最优编码问题(哈夫曼编码)(贪心)
- 贪心算法——Huffman编码(哈夫曼编码)
- 贪心算法——Huffman编码(哈夫曼编码) 收藏
- 贪心算法 - 哈夫曼编码 Huffman
- 贪心算法--哈夫曼编码问题
- Oracle 高效学习的方法论
- 移动设计模式总结(三)
- 电信光猫F660 4台限制破解
- 求最短路径之Dijkstra算法
- ajax的优缺点
- 哈夫曼编码(贪心)
- android默认设置的开关
- Struts1.x教程(一) Struts概述及其工作原理
- iOS 设备现有的分辨率如下
- Jquery 中的CheckBox、 RadioButton、 DropDownList的取值赋值
- pat 1024
- 常用的Linux快捷键 [译]
- android2.0以后获取Email
- hdu 1698 成段改变值