问题 A: DS_6.13 给定权值,哈弗曼编码、译码(by Yan)
时间限制: 20 Sec 内存限制: 256 MB
提交: 500 解决: 346
[提交][状态][讨论版]
题目描述
假设某通信报文的字符集由A,B,C,D,E,F这6个字符组成,它们在报文中出现的频度(频度均为整数值)。
(1)构造一棵哈弗曼树,依次给出各字符编码结果。
(2)给字符串进行编码。
(3)给编码串进行译码。
规定:
构建哈弗曼树时:左子树根结点权值小于等于右子树根结点权值。
生成编码时:左分支标0,右分支标1。
输入
第一行:依次输入6个整数,依次代表A,B,C,D,E,F的频度,用空格隔开。
第二行:待编码的字符串
第三行:待译码的编码串
输出
前6行依次输出各个字符及其对应编码,格式为【字符:编码】(冒号均为英文符号)
第7行:编码串
第8行:译码串
样例输入
3 4 10 8 6 5 BEE 0010000100111101
样例输出
A:000 B:001 C:10 D:01 E:111 F:110 001111111 BADBED
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 6
#define M 11
typedef char *Huffmancode[6];
typedef struct
{
int weight;
int parent,Lchild,Rchild;
}HTNode,HuffmanTree[M+1]; //零号单元不用
void select(HuffmanTree ht, int n, int *s1, int *s2){ /*挑选哈夫曼书前n项中权值
最小且parent不为0的两个值的下标*/
int c[30];
int i,j,h;
int cut = 0;
for(i=0; i<30; i++)c[i] = 0 ;
for(i=1; i<=n; i++){
if( ht[i].parent==0 ){
c[cut] = ht[i].weight;
cut++;
}
}
for(i=0; i<cut; i++){ //冒泡排序
for(j=0; j<cut-i-1; j++){
if( c[j]>c[j+1] ){
h = c[j];
c[j] = c[j+1];
c[j+1] = h;
}
}
}
for(i=1; i<=n; i++){
if(c[0]==0 || c[1]==0){
printf("error\n") ;
return ;
}
if( c[0]==ht[i].weight )
*s1 = i;
if( c[1]==ht[i].weight )
*s2 = i;
}
}
void CreatHuffmanTree(HuffmanTree ht, int w[], int n){ //创建哈夫曼树
int m = 2*n-1;
int s1,s2;
int i;
for(i=0; i<=n; i++){
ht[i].weight = w[i];
ht[i].Lchild = 0;
ht[i].Rchild = 0;
ht[i].parent = 0;
}
for(i=n+1; i<=m; i++){
ht[i].weight = 0;
ht[i].Lchild = 0;
ht[i].Rchild = 0;
ht[i].parent = 0;
}
for(i=n+1; i<=m; i++){
select(ht, i-1, &s1, &s2);
//Print(ht);
ht[i].weight = ht[s1].weight + ht[s2].weight ;
ht[i].Lchild = s1 ;
ht[i].Rchild = s2 ;
ht[s1].parent = i ;
ht[s2].parent = i ;
}
}
void CrtHuffmanCodel(HuffmanTree ht, Huffmancode hc, int n){ //哈夫曼树编码
char *cd;
int start;
int i,c,p;
cd = (char *)malloc(n * sizeof(char));
cd[n-1] = '\0';
for(i=1; i<=n; i++){
start = n-1;
c = i;
p = ht[i].parent;
while (p!=0){
--start;
if(ht[p].Lchild==c){
cd[start] = '0';
}
else
cd[start] = '1';
c = p;
p = ht[p].parent;
}
hc[i] = (char *)malloc((n - start) * sizeof(char));
strcpy(hc[i], &cd[start]);
}
free(cd);
}
void print(Huffmancode hc){ //输出哈夫曼树编码
int i;
for(i=1; i<=6; i++){
switch(i){
case 1:printf("A:%s",hc[1]);break;
case 2:printf("B:%s",hc[2]);break;
case 3:printf("C:%s",hc[3]);break;
case 4:printf("D:%s",hc[4]);break;
case 5:printf("E:%s",hc[5]);break;
case 6:printf("F:%s",hc[6]);break;
}
printf("\n");
}
}
void println(HuffmanTree ht, int p){ //输出p为叶子节点时的译码信息
switch(p){
case 1:printf("A");break;
case 2:printf("B");break;
case 3:printf("C");break;
case 4:printf("D");break;
case 5:printf("E");break;
case 6:printf("F");break;
}
}
void TransHuffmancodel(HuffmanTree ht, char *c){ //哈弗满树译码
int i,p,d;
p = M;
for(i=0; c[i]!='\0'; i++){
if (c[i]=='0'){
p = ht[p].Lchild;
if(ht[p].Lchild==0 && ht[p].Rchild==0){
println(ht, p);
p = M;
}
}
if (c[i]=='1'){
p = ht[p].Rchild;
if(ht[p].Lchild==0 && ht[p].Rchild==0){
println(ht, p);
p = M;
}
}
}
}
int main(){
int i,j;
HuffmanTree ht ;
int w[N+1];
for(i=1; i<=6; i++){
scanf("%d",&w[i]);
}
CreatHuffmanTree(ht, w, 6) ;
Huffmancode hc;
CrtHuffmanCodel(ht, hc, 6);
char s[6], c[100];
scanf("%s",s);
scanf("\n%s",c);
print(hc);
for(i=0; i<strlen(s); i++){
switch(s[i]){
case 'A':printf("%s",hc[1]);break;
case 'B':printf("%s",hc[2]);break;
case 'C':printf("%s",hc[3]);break;
case 'D':printf("%s",hc[4]);break;
case 'E':printf("%s",hc[5]);break;
case 'F':printf("%s",hc[6]);break;
}
}
printf("\n");
TransHuffmancodel(ht, c);
printf("\n");
return 0;
}