编写一个哈夫曼编码译码程序。
按词频从小到大的顺序给出各个字符(不超过30个)的词频,根据词频构造哈夫曼树,给出每个字符的哈夫曼编码,并对给出的语句进行译码。
为确保构建的哈夫曼树唯一,本题做如下限定:
(1)选择根结点权值最小的两棵二叉树时,选取权值较小者作为左子树。
(2)若多棵二叉树根结点权值相等,按先后次序分左右,先出现的作为左子树,后出现的作为右子树。
生成哈夫曼编码时,哈夫曼树左分支标记为0,右分支标记为1。
输入格式:
第一行输入字符个数n;
第二行到第n行输入相应的字符及其词频(可以是整数,与可以是小数);
最后一行输入需进行译码的串。
输出格式:
首先按树的先序顺序输出所有字符的编码,每个编码占一行;
最后一行输出需译码的原文,加上original:字样。
输出中均无空格
输入样例:
3
m1
n1
c2
10110
输出样例:
c:0
m:10
n:11
original:mnc
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
#define MAX_INT 1000
#define MAX_Double (numeric_limits<double>::max)()
using namespace std;
typedef struct TreeNode {
double weight;
char Ch;
char* code;
int parent, lchild, rchild;
}TreeNode;
typedef struct HFTree {
TreeNode* data;
int length;
}HFTree;
HFTree* initTree(double* weight, char* ch, int n) {
HFTree* T = (HFTree*)malloc(sizeof(HFTree));
T->data = (TreeNode*)malloc(sizeof(TreeNode) * (2 * n - 1));
T->length = n;
for (int i = 0; i < n; ++i) {
T->data[i].Ch = ch[i];
T->data[i].weight = weight[i];
T->data[i].parent = 0;
T->data[i].lchild = -1;
T->data[i].rchild = -1;
T->data[i].code = (char*)malloc(sizeof(char) * MAX_INT);
memset(T->data[i].code, '\0', MAX_INT);
}
return T;
}
int* selectMin(HFTree* T) {
double min = MAX_Double;
double secondMin = MAX_Double;
int minIndex;
int secondIndex;
for (int i = 0; i < T->length; ++i) {
if (T->data[i].parent == 0) {
if (T->data[i].weight < min) {
min = T->data[i].weight;
minIndex = i;
}
}
}
for (int i = 0; i < T->length; ++i) {
if (T->data[i].parent == 0 && i != minIndex) {
if (T->data[i].weight < secondMin) {
secondMin = T->data[i].weight;
secondIndex = i;
}
}
}
int* res = (int*)malloc(sizeof(int) * 2);
res[0] = minIndex;
res[1] = secondIndex;
return res;
}
void Hfmcode(HFTree* T, int n) {
for (int k = 0; k < n; k++) {
int i = 0, j = 0;
int ch = k;
char str[MAX_INT];
memset(str, '\0', MAX_INT);
int parent = T->data[k].parent;
for (i = n - 1; parent != 0; i--) {
if (T->data[parent].lchild == ch) {
str[j++] = '0';
ch = parent;
parent = T->data[ch].parent;
}
else {
str[j++] = '1';
ch = parent;
parent = T->data[ch].parent;
}
}
int f = 0;
for (int s = j - 1; s >= 0; s--) {
T->data[k].code[f] = str[s];
f++;
}
}
}
void createHFTree(HFTree* T, int nn) {
int* res;
int min;
int secondMin;
int n = T->length * 2 - 1;
for (int i = T->length; i < n; ++i) {
T->data[i].parent = 0;
res = selectMin(T);
min = res[0];
secondMin = res[1];
T->data[i].weight = T->data[min].weight + T->data[secondMin].weight;
T->data[i].lchild = min;
T->data[i].rchild = secondMin;
T->data[min].parent = i;
T->data[secondMin].parent = i;
T->length++;
}
Hfmcode(T, nn);
}
void preOrder(HFTree* T, int index) {
if (index != -1) {
if (T->data[index].lchild == -1 || T->data[index].rchild == -1)
cout << T->data[index].Ch << ":" << T->data[index].code << endl;
preOrder(T, T->data[index].lchild);
preOrder(T, T->data[index].rchild);
}
}
char* Decode(char* str, int length, HFTree* T) {
int index = length - 1, ct = 0, j = 0;
char ch;
ch = str[0];
char* res = (char*)malloc(sizeof(char) * MAX_INT);
while (true) {
if (ch == '0') {
index = T->data[index].lchild;
}
else if (ch == '1') {
index = T->data[index].rchild;
}
if (T->data[index].lchild == -1 || T->data[index].rchild == -1) {
res[ct] = T->data[index].Ch;
ct++;
index = length - 1;
}
j++;
ch = str[j];
if (j == (int)strlen(str))
break;
}
return res;
}
int main() {
int n;
scanf("%d", &n);
getchar();
char* chNums = (char*)malloc(sizeof(char) * n);
double* nuNums = (double*)malloc(sizeof(double) * n);
for (int i = 0; i < n; ++i) {
scanf("%c%lf", &chNums[i], &nuNums[i]);
getchar();
}
char str[MAX_INT];
scanf("%s", str);
getchar();
HFTree* T = initTree(nuNums, chNums, n);
createHFTree(T, n);
preOrder(T, T->length - 1);
cout << "original:" << Decode(str, T->length, T) << endl;
return 0;
}