帮我解读#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_TREE_HT 100
#define MAX_CHAR 256
// 哈夫曼树节点
typedef struct Node {
char data;
unsigned freq;
struct Node *left, *right;
} Node;
// 最小堆
typedef struct MinHeap {
int size;
Node** array;
} MinHeap;
// 编码表
typedef struct Code {
char ch;
char bits[MAX_TREE_HT];
} Code;
// 创建新节点
Node* createNode(char data, unsigned freq) {
Node* node = (Node*)malloc(sizeof(Node));
node->data = data;
node->freq = freq;
node->left = node->right = NULL;
return node;
}
// 创建最小堆
MinHeap* createMinHeap(int capacity) {
MinHeap* heap = (MinHeap*)malloc(sizeof(MinHeap));
heap->size = 0;
heap->array = (Node**)malloc(capacity * sizeof(Node*));
return heap;
}
// 交换节点
void swapNodes(Node** a, Node** b) {
Node* temp = *a;
*a = *b;
*b = temp;
}
// 堆化
void heapify(MinHeap* heap, int idx) {
int smallest = idx;
int left = 2 * idx + 1;
int right = 2 * idx + 2;
if (left < heap->size && heap->array[left]->freq < heap->array[smallest]->freq)
smallest = left;
if (right < heap->size && heap->array[right]->freq < heap->array[smallest]->freq)
smallest = right;
if (smallest != idx) {
swapNodes(&heap->array[smallest], &heap->array[idx]);
heapify(heap, smallest);
}
}
// 提取最小节点
Node* extractMin(MinHeap* heap) {
Node* temp = heap->array[0];
heap->array[0] = heap->array[heap->size - 1];
heap->size--;
heapify(heap, 0);
return temp;
}
// 插入节点
void insertNode(MinHeap* heap, Node* node) {
heap->size++;
int i = heap->size - 1;
while (i && node->freq < heap->array[(i - 1) / 2]->freq) {
heap->array[i] = heap->array[(i - 1) / 2];
i = (i - 1) / 2;
}
heap->array[i] = node;
}
// 构建最小堆
void buildMinHeap(MinHeap* heap) {
int n = heap->size - 1;
for (int i = (n - 1) / 2; i >= 0; i--)
heapify(heap, i);
}
// 构建哈夫曼树
Node* buildHuffmanTree(char data[], int freq[], int size) {
MinHeap* heap = createMinHeap(size);
for (int i = 0; i < size; i++)
heap->array[i] = createNode(data[i], freq[i]);
heap->size = size;
buildMinHeap(heap);
while (heap->size > 1) {
Node* left = extractMin(heap);
Node* right = extractMin(heap);
Node* parent = createNode('$', left->freq + right->freq);
parent->left = left;
parent->right = right;
insertNode(heap, parent);
}
return extractMin(heap);
}
// 生成编码表
void generateCodes(Node* root, char code[], int top, Code codes[], int* index) {
if (root->left) {
code[top] = '0';
generateCodes(root->left, code, top + 1, codes, index);
}
if (root->right) {
code[top] = '1';
generateCodes(root->right, code, top + 1, codes, index);
}
if (!root->left && !root->right) {
codes[*index].ch = root->data;
for (int i = 0; i < top; i++)
codes[*index].bits[i] = code[i];
codes[*index].bits[top] = '\0';
(*index)++;
}
}
// 统计字符频率
void countChars(const char* text, int freq[]) {
for (int i = 0; i < MAX_CHAR; i++) freq[i] = 0;
for (int i = 0; text[i] != '\0'; i++)
freq[(unsigned char)text[i]]++;
}
// 编码文本
char* encode(const char* text, Code codes[], int codeCount) {
int length = 0;
// 计算编码后长度
for (int i = 0; text[i] != '\0'; i++) {
for (int j = 0; j < codeCount; j++) {
if (codes[j].ch == text[i]) {
length += strlen(codes[j].bits);
break;
}
}
}
char* encoded = (char*)malloc(length + 1);
encoded[0] = '\0';
// 生成编码
for (int i = 0; text[i] != '\0'; i++) {
for (int j = 0; j < codeCount; j++) {
if (codes[j].ch == text[i]) {
strcat(encoded, codes[j].bits);
break;
}
}
}
return encoded;
}
// 解码文本(使用哈夫曼树)
char* decodeWithTree(const char* encoded, Node* root) {
if (root == NULL) return NULL;
char* decoded = (char*)malloc(strlen(encoded) + 1);
int index = 0;
Node* current = root;
for (int i = 0; encoded[i] != '\0'; i++) {
if (encoded[i] == '0') {
current = current->left;
} else if (encoded[i] == '1') {
current = current->right;
} else {
printf("错误:编码中包含非法字符 '%c'\n", encoded[i]);
free(decoded);
return NULL;
}
if (current == NULL) {
printf("错误:解码路径错误\n");
free(decoded);
return NULL;
}
// 到达叶子节点
if (!current->left && !current->right) {
decoded[index++] = current->data;
current = root;
}
}
decoded[index] = '\0';
return decoded;
}
// 解码文本(使用编码表)
char* decodeWithTable(const char* encoded, Code codes[], int codeCount) {
char* decoded = (char*)malloc(strlen(encoded) + 1);
decoded[0] = '\0';
char currentCode[MAX_TREE_HT] = "";
int codePos = 0;
for (int i = 0; encoded[i] != '\0'; i++) {
currentCode[codePos++] = encoded[i];
currentCode[codePos] = '\0';
// 查找匹配的编码
for (int j = 0; j < codeCount; j++) {
if (strcmp(currentCode, codes[j].bits) == 0) {
// 找到匹配,添加对应字符
int len = strlen(decoded);
decoded[len] = codes[j].ch;
decoded[len + 1] = '\0';
// 重置当前编码
codePos = 0;
currentCode[0] = '\0';
break;
}
}
// 防止无限循环
if (codePos >= MAX_TREE_HT - 1) {
printf("错误:未找到匹配的编码\n");
free(decoded);
return NULL;
}
}
return decoded;
}
// 显示编码表
void showCodes(Code codes[], int count) {
printf("\n字符\t编码\n");
printf("----\t----\n");
for (int i = 0; i < count; i++) {
if (codes[i].ch == ' ') printf("空格");
else if (codes[i].ch == '\n') printf("换行");
else if (codes[i].ch == '\t') printf("制表符");
else printf("%c", codes[i].ch);
printf("\t%s\n", codes[i].bits);
}
}
// 释放树内存
void freeTree(Node* root) {
if (root == NULL) return;
freeTree(root->left);
freeTree(root->right);
free(root);
}
// 显示菜单
void showMenu() {
printf("\n=== 哈夫曼编码/译码器 ===\n");
printf("1. 编码文本\n");
printf("2. 译码文本(使用哈夫曼树)\n");
printf("3. 译码文本(使用编码表)\n");
printf("4. 退出\n");
printf("请选择操作: ");
}
int main() {
int choice;
char text[1000];
char encodedText[5000];
Node* huffmanTree = NULL;
Code codes[MAX_CHAR];
int codeCount = 0;
while (1) {
showMenu();
scanf("%d", &choice);
getchar(); // 消耗换行符
switch (choice) {
case 1: {
// 编码文本
printf("请输入要编码的文本: ");
fgets(text, sizeof(text), stdin);
// 移除换行符
int len = strlen(text);
if (len > 0 && text[len-1] == '\n')
text[len-1] = '\0';
if (strlen(text) == 0) {
printf("输入为空!\n");
break;
}
// 统计频率
int freq[MAX_CHAR];
countChars(text, freq);
// 收集出现过的字符
char chars[MAX_CHAR];
int freqs[MAX_CHAR];
int charCount = 0;
for (int i = 0; i < MAX_CHAR; i++) {
if (freq[i] > 0) {
chars[charCount] = (char)i;
freqs[charCount] = freq[i];
charCount++;
}
}
// 构建哈夫曼树
if (huffmanTree != NULL) {
freeTree(huffmanTree);
}
huffmanTree = buildHuffmanTree(chars, freqs, charCount);
// 生成编码表
codeCount = 0;
char tempCode[MAX_TREE_HT];
generateCodes(huffmanTree, tempCode, 0, codes, &codeCount);
// 显示编码表
showCodes(codes, codeCount);
// 编码文本
char* encoded = encode(text, codes, codeCount);
printf("\n编码结果: %s\n", encoded);
// 保存编码结果供后续使用
strncpy(encodedText, encoded, sizeof(encodedText)-1);
encodedText[sizeof(encodedText)-1] = '\0';
// 计算压缩率
int originalBits = strlen(text) * 8;
int encodedBits = strlen(encoded);
double ratio = (1 - (double)encodedBits / originalBits) * 100;
printf("\n压缩统计:\n");
printf("原始: %d bits\n", originalBits);
printf("编码: %d bits\n", encodedBits);
printf("压缩率: %.1f%%\n", ratio);
free(encoded);
break;
}
case 2: {
// 使用哈夫曼树译码
if (huffmanTree == NULL) {
printf("请先编码文本生成哈夫曼树!\n");
break;
}
printf("请输入要译码的二进制串: ");
fgets(encodedText, sizeof(encodedText), stdin);
// 移除换行符
int len = strlen(encodedText);
if (len > 0 && encodedText[len-1] == '\n')
encodedText[len-1] = '\0';
// 验证输入是否为二进制
for (int i = 0; encodedText[i] != '\0'; i++) {
if (encodedText[i] != '0' && encodedText[i] != '1') {
printf("错误:输入必须为二进制串(只包含0和1)\n");
break;
}
}
char* decoded = decodeWithTree(encodedText, huffmanTree);
if (decoded != NULL) {
printf("译码结果: %s\n", decoded);
free(decoded);
}
break;
}
case 3: {
// 使用编码表译码
if (codeCount == 0) {
printf("请先编码文本生成编码表!\n");
break;
}
printf("请输入要译码的二进制串: ");
fgets(encodedText, sizeof(encodedText), stdin);
// 移除换行符
int len = strlen(encodedText);
if (len > 0 && encodedText[len-1] == '\n')
encodedText[len-1] = '\0';
char* decoded = decodeWithTable(encodedText, codes, codeCount);
if (decoded != NULL) {
printf("译码结果: %s\n", decoded);
free(decoded);
}
break;
}
case 4:
printf("程序退出!\n");
if (huffmanTree != NULL) {
freeTree(huffmanTree);
}
return 0;
default:
printf("无效选择!\n");
}
}
return 0;
}