显示每个字符的哈夫曼编码。 3文件读入一文本,显示对其编码结果,并存盘 4文件读入一组编码,显示对其译码结果,并存盘。 数据结构 c语言 详细注解
时间: 2024-03-17 15:47:53 浏览: 62
首先,需要实现哈夫曼编码的算法,具体步骤如下:
1. 统计每个字符的出现频率
2. 将每个字符以及其出现频率作为叶子节点构建一棵哈夫曼树
3. 遍历哈夫曼树,给每个字符赋予对应的编码(左子树为0,右子树为1)
4. 将编码结果输出并存盘
具体实现可以使用C语言的数据结构来进行,以下是可能用到的一些数据结构及其注解:
1. 字符出现频率的统计可以使用数组来实现,例如:
```c
int freq[256] = {0}; // 用于统计每个字符出现的频率,数组下标对应字符ASCII码,初始化为0
```
2. 哈夫曼树可以使用二叉树来实现,例如:
```c
struct HuffmanNode {
char data; // 存储字符
int freq; // 存储出现频率
struct HuffmanNode *leftChild; // 左子树
struct HuffmanNode *rightChild; // 右子树
};
```
3. 哈夫曼编码可以使用字符串来实现,例如:
```c
char code[256] = {0}; // 用于存储每个字符的编码,数组下标对应字符ASCII码,初始化为0
```
4. 读写文件可以使用标准库中的文件操作函数来实现,例如:
```c
FILE *fp; // 文件指针
fp = fopen("filename.txt", "r"); // 打开文件,以只读模式打开
if (fp == NULL) {
printf("Failed to open file.");
exit(1);
}
// 读取文件内容
char buffer[1024];
while (fgets(buffer, 1024, fp) != NULL) {
// 对文件内容进行处理
}
fclose(fp); // 关闭文件
```
根据以上数据结构及其注解,我们可以实现哈夫曼编码的算法。具体实现代码如下(仅供参考):
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct HuffmanNode {
char data; // 存储字符
int freq; // 存储出现频率
struct HuffmanNode *leftChild; // 左子树
struct HuffmanNode *rightChild; // 右子树
};
struct MinHeap {
int size; // 当前堆中元素个数
int capacity; // 堆的容量
struct HuffmanNode **array; // 存储哈夫曼树节点的数组
};
// 创建一个新的哈夫曼树节点
struct HuffmanNode *newHuffmanNode(char data, int freq) {
struct HuffmanNode *node = (struct HuffmanNode *) malloc(sizeof(struct HuffmanNode));
node->data = data;
node->freq = freq;
node->leftChild = NULL;
node->rightChild = NULL;
return node;
}
// 创建一个新的最小堆
struct MinHeap *createMinHeap(int capacity) {
struct MinHeap *heap = (struct MinHeap *) malloc(sizeof(struct MinHeap));
heap->size = 0;
heap->capacity = capacity;
heap->array = (struct HuffmanNode **) malloc(capacity * sizeof(struct HuffmanNode *));
return heap;
}
// 交换两个节点
void swapNodes(struct HuffmanNode **a, struct HuffmanNode **b) {
struct HuffmanNode *temp = *a;
*a = *b;
*b = temp;
}
// 维护堆的性质
void minHeapify(struct MinHeap *heap, int index) {
int smallest = index;
int left = 2 * index + 1;
int right = 2 * index + 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 != index) {
swapNodes(&heap->array[smallest], &heap->array[index]);
minHeapify(heap, smallest);
}
}
// 检查堆是否为空
int isMinHeapEmpty(struct MinHeap *heap) {
return (heap->size == 0);
}
// 获取堆中最小的节点
struct HuffmanNode *extractMin(struct MinHeap *heap) {
struct HuffmanNode *minNode = heap->array[0];
heap->array[0] = heap->array[heap->size - 1];
heap->size--;
minHeapify(heap, 0);
return minNode;
}
// 插入一个新的节点到堆中
void insertMinHeap(struct MinHeap *heap, struct HuffmanNode *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;
}
// 检查堆中是否只有一个节点
int isSizeOne(struct MinHeap *heap) {
return (heap->size == 1);
}
// 构建哈夫曼树
struct HuffmanNode *buildHuffmanTree(char *data, int *freq, int size) {
struct HuffmanNode *left, *right, *top;
struct MinHeap *heap = createMinHeap(size);
for (int i = 0; i < size; i++) {
insertMinHeap(heap, newHuffmanNode(data[i], freq[i]));
}
while (!isMinHeapEmpty(heap)) {
left = extractMin(heap);
right = extractMin(heap);
top = newHuffmanNode('$', left->freq + right->freq);
top->leftChild = left;
top->rightChild = right;
insertMinHeap(heap, top);
}
return extractMin(heap);
}
// 将编码结果输出并存盘
void printCodes(struct HuffmanNode *root, char *prefix, char *code) {
if (root) {
if (root->leftChild == NULL && root->rightChild == NULL) {
printf("%c: %s\n", root->data, prefix);
int index = (int) root->data;
strcpy(&code[index], prefix);
} else {
int len = strlen(prefix);
char *leftPrefix = (char *) malloc((len + 2) * sizeof(char));
strcpy(leftPrefix, prefix);
leftPrefix[len] = '0';
leftPrefix[len + 1] = '\0';
printCodes(root->leftChild, leftPrefix, code);
char *rightPrefix = (char *) malloc((len + 2) * sizeof(char));
strcpy(rightPrefix, prefix);
rightPrefix[len] = '1';
rightPrefix[len + 1] = '\0';
printCodes(root->rightChild, rightPrefix, code);
}
}
}
// 哈夫曼编码函数
void huffmanEncode(char *data, int size) {
int freq[256] = {0};
char code[256] = {0};
// 统计每个字符的出现频率
for (int i = 0; i < size; i++) {
freq[(int) data[i]]++;
}
// 构建哈夫曼树
struct HuffmanNode *root = buildHuffmanTree(data, freq, 256);
// 输出每个字符的编码
char prefix[256] = {'\0'};
printCodes(root, prefix, code);
// 将编码结果写入文件
FILE *fp;
fp = fopen("code.txt", "w");
if (fp == NULL) {
printf("Failed to open file.");
exit(1);
}
fwrite(code, 1, 256, fp);
fclose(fp);
}
// 哈夫曼译码函数
void huffmanDecode() {
char code[256] = {0};
char data[256] = {0};
char buffer[1024];
// 读取编码结果
FILE *fp;
fp = fopen("code.txt", "r");
if (fp == NULL) {
printf("Failed to open file.");
exit(1);
}
fread(code, 1, 256, fp);
fclose(fp);
// 将编码结果转换为哈夫曼树
struct HuffmanNode *root = newHuffmanNode('$', 0);
for (int i = 0; i < 256; i++) {
if (code[i] != '\0') {
struct HuffmanNode *node = root;
for (int j = 0; j < strlen(&code[i]); j++) {
if (code[i + j] == '0') {
if (node->leftChild == NULL) {
node->leftChild = newHuffmanNode('$', 0);
}
node = node->leftChild;
} else if (code[i + j] == '1') {
if (node->rightChild == NULL) {
node->rightChild = newHuffmanNode('$', 0);
}
node = node->rightChild;
}
}
node->data = (char) i;
}
}
// 读取译码用的编码
fp = fopen("input.txt", "r");
if (fp == NULL) {
printf("Failed to open file.");
exit(1);
}
while (fgets(buffer, 1024, fp) != NULL) {
strcat(data, buffer);
}
fclose(fp);
// 译码并将结果写入文件
fp = fopen("output.txt", "w");
if (fp == NULL) {
printf("Failed to open file.");
exit(1);
}
struct HuffmanNode *node = root;
for (int i = 0; i < strlen(data); i++) {
if (data[i] == '0') {
node = node->leftChild;
} else if (data[i] == '1') {
node = node->rightChild;
}
if (node->leftChild == NULL && node->rightChild == NULL) {
fwrite(&node->data, 1, 1, fp);
node = root;
}
}
fclose(fp);
}
int main() {
// 读取需要编码的文件
char data[1024];
FILE *fp;
fp = fopen("input.txt", "r");
if (fp == NULL) {
printf("Failed to open file.");
exit(1);
}
fgets(data, 1024, fp);
fclose(fp);
// 进行哈夫曼编码
huffmanEncode(data, strlen(data));
// 进行哈夫曼译码
huffmanDecode();
return 0;
}
```
阅读全文