编写C语言代码:根据给定的n个字符及其权值设计各字符的哈夫曼编码键盘输入一段英文句子统计句子中出现的英文字母数目不含标点符号以及各个英文字母的出现次数及频率。然后设计各个英文字母的哈夫曼编码的码字。选定一个英文字母序列根据上述哈夫曼编码方法得到码字序列后再对码字序列译码
- 哈夫曼编码
先定义一个结构体来存储字符和对应的权值:
typedef struct {
char ch;
int weight;
} CharWeight;
假设有n个字符及其权值,存储在一个数组charWeights中。接下来,按照哈夫曼编码的算法,构造哈夫曼树,并计算每个字符的哈夫曼编码。
// 哈夫曼树节点
typedef struct HTNode {
int weight;
int parent;
int leftChild;
int rightChild;
} HTNode;
// 哈夫曼编码节点
typedef struct HCNode {
char ch;
char *code;
} HCNode;
// 构造哈夫曼树
void createHuffmanTree(CharWeight *charWeights, int n, HTNode *ht) {
int i, j, min1, min2;
int m = 2 * n - 1;
ht[0].weight = m;
for (i = 1; i <= m; i++) {
ht[i].parent = 0;
ht[i].leftChild = 0;
ht[i].rightChild = 0;
}
for (i = 1; i <= n; i++) {
ht[i].weight = charWeights[i - 1].weight;
}
for (i = n + 1; i <= m; i++) {
min1 = min2 = INT_MAX;
for (j = 1; j < i; j++) {
if (ht[j].parent == 0) {
if (ht[j].weight < min1) {
min2 = min1;
min1 = ht[j].weight;
} else if (ht[j].weight < min2) {
min2 = ht[j].weight;
}
}
}
ht[i].weight = min1 + min2;
for (j = 1; j < i; j++) {
if (ht[j].parent == 0 && ht[j].weight == min1) {
ht[j].parent = i;
ht[i].leftChild = j;
} else if (ht[j].parent == 0 && ht[j].weight == min2) {
ht[j].parent = i;
ht[i].rightChild = j;
}
}
}
}
// 计算哈夫曼编码
void getHuffmanCode(CharWeight *charWeights, int n, HTNode *ht, HCNode *hc) {
int i, j, k;
char *code = (char *) malloc((n + 1) * sizeof(char));
code[n] = '\0';
for (i = 1; i <= n; i++) {
hc[i].ch = charWeights[i - 1].ch;
k = i;
while (ht[k].parent != 0) {
if (ht[k].parent > 0 && ht[ht[k].parent].leftChild == k) {
code[--k] = '0';
} else if (ht[k].parent > 0 && ht[ht[k].parent].rightChild == k) {
code[--k] = '1';
}
k = ht[k].parent;
}
hc[i].code = (char *) malloc((n - k) * sizeof(char));
strcpy(hc[i].code, &code[k]);
}
free(code);
}
- 统计英文字母数目、出现次数和频率
假设输入的英文句子存储在一个字符串sentence中,先将所有的大写字母转换成小写字母,然后统计每个字母出现的次数和频率。
// 统计英文字母数目、出现次数和频率
void countLetters(char *sentence, int *count, double *frequency) {
int i;
for (i = 0; i < 26; i++) {
count[i] = 0;
}
int len = strlen(sentence);
int letterCount = 0;
for (i = 0; i < len; i++) {
if (isalpha(sentence[i])) {
letterCount++;
sentence[i] = tolower(sentence[i]);
count[sentence[i] - 'a']++;
}
}
for (i = 0; i < 26; i++) {
frequency[i] = count[i] * 1.0 / letterCount;
}
}
- 根据哈夫曼编码对字符串进行编码和解码
先定义一个结构体来存储字符和对应的哈夫曼编码:
// 哈夫曼编码节点
typedef struct HCNode {
char ch;
char *code;
} HCNode;
假设要编码的字符串存储在一个字符串input中,选定的英文字母序列存储在一个字符串letterSeq中,哈夫曼编码存储在一个数组hc中。先将input中的大写字母转换成小写字母,然后根据letterSeq和hc数组获得码字序列。
// 根据哈夫曼编码对字符串进行编码
char *encode(char *input, char *letterSeq, HCNode *hc) {
int i, j, k;
int len = strlen(input);
char *output = (char *) malloc((len + 1) * sizeof(char));
output[len] = '\0';
for (i = 0; i < len; i++) {
if (isalpha(input[i])) {
input[i] = tolower(input[i]);
for (j = 0; j < strlen(letterSeq); j++) {
if (input[i] == letterSeq[j]) {
k = j + 1;
strcat(output, hc[k].code);
break;
}
}
}
}
return output;
}
// 根据哈夫曼编码对码字序列进行解码
char *decode(char *input, HCNode *hc, int n) {
int i, j;
int len = strlen(input);
char *output = (char *) malloc((len / n + 1) * sizeof(char));
output[len / n] = '\0';
for (i = 0; i < len; i += n) {
char *code = (char *) malloc((n + 1) * sizeof(char));
strncpy(code, &input[i], n);
code[n] = '\0';
for (j = 1; j <= n; j++) {
if (strcmp(code, hc[j].code) == 0) {
output[i / n] = hc[j].ch;
break;
}
}
free(code);
}
return output;
}
完整代码如下
原文地址: https://www.cveoy.top/t/topic/hbWE 著作权归作者所有。请勿转载和采集!