用C语言编写代码输入一个字符串(该字符串可能包括英文字母、数字和标点符号),试求将该字符串进行哈夫曼编码的长度
时间: 2024-05-05 16:21:45 浏览: 95
要求对字符串进行哈夫曼编码,需要先统计每个字符出现的频率,然后构建哈夫曼树,并生成每个字符的哈夫曼编码。最后将每个字符的哈夫曼编码拼接起来,便得到了整个字符串的哈夫曼编码。
以下是一个用C语言实现字符串哈夫曼编码长度的示例代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_CHARACTERS 256
// 哈夫曼树节点结构体
typedef struct HuffmanNode {
char character; // 字符
int frequency; // 频率
struct HuffmanNode* left; // 左子树
struct HuffmanNode* right; // 右子树
} HuffmanNode;
// 哈夫曼编码结构体
typedef struct HuffmanCode {
char character; // 字符
char* code; // 编码
} HuffmanCode;
// 统计字符串中每个字符的频率
int* countFrequencies(char* str) {
int* frequencies = (int*)calloc(MAX_CHARACTERS, sizeof(int));
while (*str) {
frequencies[*str]++;
str++;
}
return frequencies;
}
// 创建一个哈夫曼树节点
HuffmanNode* createHuffmanNode(char character, int frequency) {
HuffmanNode* node = (HuffmanNode*)malloc(sizeof(HuffmanNode));
node->character = character;
node->frequency = frequency;
node->left = NULL;
node->right = NULL;
return node;
}
// 从最小堆中取出频率最小的两个节点
void extractMin(HuffmanNode** heap, int* heapSize, HuffmanNode** min1, HuffmanNode** min2) {
int i, minIndex = 0;
*min1 = heap[0];
for (i = 1; i < *heapSize; i++) {
if (heap[i]->frequency < (*min1)->frequency) {
minIndex = i;
*min2 = *min1;
*min1 = heap[i];
} else if (heap[i]->frequency < (*min2)->frequency) {
*min2 = heap[i];
}
}
heap[minIndex] = NULL;
*heapSize -= 1;
}
// 向最小堆中插入一个节点
void insert(HuffmanNode** heap, int* heapSize, HuffmanNode* node) {
int i = *heapSize;
while (i > 0 && heap[(i - 1) / 2]->frequency > node->frequency) {
heap[i] = heap[(i - 1) / 2];
i = (i - 1) / 2;
}
heap[i] = node;
*heapSize += 1;
}
// 构建哈夫曼树
HuffmanNode* buildHuffmanTree(int* frequencies) {
int i, heapSize = 0;
HuffmanNode* heap[MAX_CHARACTERS];
memset(heap, 0, MAX_CHARACTERS * sizeof(HuffmanNode*));
for (i = 0; i < MAX_CHARACTERS; i++) {
if (frequencies[i] > 0) {
insert(heap, &heapSize, createHuffmanNode(i, frequencies[i]));
}
}
while (heapSize > 1) {
HuffmanNode *min1, *min2, *parent;
extractMin(heap, &heapSize, &min1, &min2);
parent = createHuffmanNode('\0', min1->frequency + min2->frequency);
parent->left = min1;
parent->right = min2;
insert(heap, &heapSize, parent);
}
return heap[0];
}
// 生成每个字符的哈夫曼编码
void generateHuffmanCodes(HuffmanNode* root, char* code, int codeLength, HuffmanCode* codes) {
if (root->left == NULL && root->right == NULL) {
int i;
for (i = 0; i < MAX_CHARACTERS; i++) {
if (root->character == i) {
codes[i].character = root->character;
codes[i].code = (char*)malloc((codeLength + 1) * sizeof(char));
strncpy(codes[i].code, code, codeLength);
codes[i].code[codeLength] = '\0';
break;
}
}
} else {
code[codeLength] = '0';
generateHuffmanCodes(root->left, code, codeLength + 1, codes);
code[codeLength] = '1';
generateHuffmanCodes(root->right, code, codeLength + 1, codes);
}
}
// 计算字符串的哈夫曼编码长度
int calculateHuffmanCodeLength(char* str) {
int* frequencies = countFrequencies(str);
HuffmanNode* root = buildHuffmanTree(frequencies);
HuffmanCode codes[MAX_CHARACTERS];
memset(codes, 0, MAX_CHARACTERS * sizeof(HuffmanCode));
generateHuffmanCodes(root, (char*)calloc(MAX_CHARACTERS, sizeof(char)), 0, codes);
int length = 0;
while (*str) {
length += strlen(codes[*str].code);
str++;
}
return length;
}
int main() {
char str[] = "hello, world!";
int length = calculateHuffmanCodeLength(str);
printf("The length of the Huffman code for \"%s\" is %d.\n", str, length);
return 0;
}
```
在上面的示例代码中,我们首先统计了字符串中每个字符出现的频率,然后根据频率构建了哈夫曼树,并生成了每个字符的哈夫曼编码。最后我们遍历字符串,将每个字符的哈夫曼编码长度累加起来,就得到了整个字符串的哈夫曼编码长度。
阅读全文