题目描述
假设某通信报文的字符集由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
//
// Created by haoren on 2019/11/6.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 100
#define M 2*N-1
//哈夫曼树结构
typedef struct node{
int weight;
int parent, leftChild, rightChild;
char data;
}HTNode, HuffmanTree[M+1];
//编码结构
typedef char * HuffmanCode[N+1];
//找最小,次小函数
void select(HuffmanTree ht, int n, int *s1, int *s2) {
int temp;
for (int i = 1; i <= n; i++) {
if (ht[i].parent == 0) {
temp = i;
break;
}
}
for (int i = 1; i <= n; i++) {
if (ht[i].parent == 0) {
if (ht[i].weight < ht[temp].weight)
temp = i;
}
}
*s1 = temp;
for (int i = 1; i <= n; i++) {
if (ht[i].parent == 0 && i != *s1) {
temp = i;
break;
}
}
for (int i = 1; i <= n; i++) {
if (ht[i].parent == 0 && i != *s1)
{
if (ht[i].weight < ht[temp].weight)
temp = i;
}
}
*s2 = temp;
}
//创建哈夫曼树
void CrtHuffmanTree(HuffmanTree ht, int w[], int n) {
int m = 2*n-1;
for (int i = 1; i <= n; i++) {
ht[i].weight = w[i];
ht[i].data = 'A'+i-1;
ht[i].parent = 0;
ht[i].leftChild = 0;
ht[i].rightChild = 0;
}
for (int i = n+1; i <= m; i++) {
ht[i].weight = 0;
ht[i].parent = 0;
ht[i].leftChild = 0;
ht[i].rightChild = 0;
}
for (int i = n+1; i <= m; i++) {
int s1, s2;
select(ht, i-1, &s1, &s2);
ht[i].weight = ht[s1].weight+ht[s2].weight;
ht[i].leftChild = s1;
ht[i].rightChild = s2;
ht[s1].parent = i;
ht[s2].parent = i;
}
}
//哈夫曼编码
void CrtHuffmanCode(HuffmanTree ht, HuffmanCode hc, int n){
char *cd;
int start;
cd = (char*)malloc(n*sizeof(char));
cd[n-1] = '\0';
for (int i = 1; i <= n; i++) {
start = n-1;
int c = i, p = ht[i].parent;
while(p) {
--start;
if (ht[p].leftChild == 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 DeCode (HuffmanTree ht, char ch[]) {
int m = 11;//由于只有6个节点,这里直接写11
for (int i = 0; i < strlen(ch); i++) {
if (ch[i] == '0')
m = ht[m].leftChild;
else
m = ht[m].rightChild;
if (ht[m].leftChild == 0) {
printf("%c", ht[m].data);
m = 11;
}
}
}
int main(void) {
HuffmanTree HFMTree;
int w[7];
for (int i = 1; i <= 6; i++) {
scanf("%d", &w[i]);
}
char ch[10]; //编码时输入字符串
char ch1[100];//译码时输入字符串
scanf("%s", ch);
scanf("%s", ch1);
CrtHuffmanTree(HFMTree, w, 6);
HuffmanCode HFMCode;
CrtHuffmanCode(HFMTree, HFMCode, 6);
for(int i = 1; i <= 6; i++) {
printf("%c:%s\n",'A'+i-1, HFMCode[i]);
}
for (int i = 0; i < strlen(ch); i++) {
if (ch[i] == 'A')
printf("%s", HFMCode[1]);
else if (ch[i] == 'B')
printf("%s", HFMCode[2]);
else if (ch[i] == 'C')
printf("%s", HFMCode[3]);
else if (ch[i] == 'D')
printf("%s", HFMCode[4]);
else if (ch[i] == 'E')
printf("%s", HFMCode[5]);
else if (ch[i] == 'F')
printf("%s", HFMCode[6]);
}
printf("\n");
DeCode(HFMTree, ch1);
return 0;
}