设计一个c语言代码,基于哈夫曼树的数据压缩算法
时间: 2023-11-23 10:09:55 浏览: 155
下面是一个基于哈夫曼树的数据压缩算法的C语言代码实现:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_TREE_HT 100
// 哈夫曼树节点结构体
struct HuffmanNode {
char data;
int freq;
struct HuffmanNode *left, *right;
};
// 哈夫曼编码结构体
struct HuffmanCode {
char data;
char *code;
};
// 哈夫曼树节点优先队列结构体
struct PriorityQueueNode {
struct HuffmanNode *node;
struct PriorityQueueNode *next;
};
// 创建哈夫曼树节点
struct HuffmanNode* createHuffmanNode(char data, int freq) {
struct HuffmanNode* node = (struct HuffmanNode*) malloc(sizeof(struct HuffmanNode));
node->data = data;
node->freq = freq;
node->left = NULL;
node->right = NULL;
return node;
}
// 交换两个哈夫曼树节点
void swap(struct PriorityQueueNode** a, struct PriorityQueueNode** b) {
struct PriorityQueueNode *t = *a;
*a = *b;
*b = t;
}
// 判断队列是否为空
int isEmpty(struct PriorityQueueNode* root) {
return !root;
}
// 插入哈夫曼树节点优先队列
void insert(struct PriorityQueueNode** root, struct HuffmanNode* node) {
struct PriorityQueueNode* temp = (struct PriorityQueueNode*) malloc(sizeof(struct PriorityQueueNode));
temp->node = node;
temp->next = NULL;
if (*root == NULL || (*root)->node->freq >= node->freq) {
temp->next = *root;
*root = temp;
} else {
struct PriorityQueueNode* current = *root;
while (current->next != NULL && current->next->node->freq < node->freq) {
current = current->next;
}
temp->next = current->next;
current->next = temp;
}
}
// 删除哈夫曼树节点优先队列的头节点
struct HuffmanNode* delete(struct PriorityQueueNode** root) {
struct PriorityQueueNode* temp = *root;
struct HuffmanNode* node = temp->node;
*root = (*root)->next;
free(temp);
return node;
}
// 建立哈夫曼树
struct HuffmanNode* buildHuffmanTree(char data[], int freq[], int size) {
struct HuffmanNode *left, *right, *top;
struct PriorityQueueNode *root = NULL;
for (int i = 0; i < size; i++) {
insert(&root, createHuffmanNode(data[i], freq[i]));
}
while (!isEmpty(root) && root->next != NULL) {
left = delete(&root);
right = delete(&root);
top = createHuffmanNode('$', left->node->freq + right->node->freq);
top->left = left->node;
top->right = right->node;
insert(&root, top);
}
return delete(&root);
}
// 打印哈夫曼编码
void printHuffmanCode(struct HuffmanNode* root, char* code, int top, struct HuffmanCode codes[]) {
if (root->left) {
code[top] = '0';
printHuffmanCode(root->left, code, top + 1, codes);
}
if (root->right) {
code[top] = '1';
printHuffmanCode(root->right, code, top + 1, codes);
}
if (!root->left && !root->right) {
codes[root->data].data = root->data;
codes[root->data].code = (char*) malloc(sizeof(char) * (top + 1));
strncpy(codes[root->data].code, code, top);
codes[root->data].code[top] = '\0';
}
}
// 哈夫曼编码
void huffmanEncode(char data[], int freq[], int size, struct HuffmanCode codes[]) {
struct HuffmanNode* root = buildHuffmanTree(data, freq, size);
char code[MAX_TREE_HT];
int top = 0;
printHuffmanCode(root, code, top, codes);
}
// 压缩数据
void compressData(char data[], struct HuffmanCode codes[], int size) {
FILE *fp, *fp2;
fp = fopen("compressed.txt", "w");
fp2 = fopen("codes.txt", "w");
for (int i = 0; i < strlen(data); i++) {
fprintf(fp, "%s", codes[data[i]].code);
}
for (int i = 0; i < size; i++) {
if (codes[i].code != NULL) {
fprintf(fp2, "%c %s\n", codes[i].data, codes[i].code);
}
}
fclose(fp);
fclose(fp2);
}
// 解压数据
void decompressData() {
FILE *fp, *fp2, *fp3;
fp = fopen("compressed.txt", "r");
fp2 = fopen("codes.txt", "r");
fp3 = fopen("decompressed.txt", "w");
struct HuffmanCode codes[128];
for (int i = 0; i < 128; i++) {
codes[i].data = '\0';
codes[i].code = NULL;
}
char d, c[100];
while (fscanf(fp2, "%c%s\n", &d, c) != EOF) {
codes[d].data = d;
codes[d].code = (char*) malloc(sizeof(char) * strlen(c));
strncpy(codes[d].code, c, strlen(c));
codes[d].code[strlen(c)] = '\0';
}
fseek(fp, 0L, SEEK_END);
long int size = ftell(fp);
fseek(fp, 0L, SEEK_SET);
char* compressedData = (char*) malloc(sizeof(char) * size);
fgets(compressedData, size, fp);
char temp[100];
int j = 0;
for (int i = 0; i <= strlen(compressedData); i++) {
if (compressedData[i] == '0' || compressedData[i] == '1') {
temp[j++] = compressedData[i];
temp[j] = '\0';
for (int k = 0; k < 128; k++) {
if (codes[k].code != NULL && strcmp(temp, codes[k].code) == 0) {
fprintf(fp3, "%c", codes[k].data);
j = 0;
break;
}
}
}
}
fclose(fp);
fclose(fp2);
fclose(fp3);
}
// 测试
int main() {
char data[] = {'a', 'b', 'c', 'd', 'e', 'f'};
int freq[] = {5, 9, 12, 13, 16, 45};
int size = sizeof(data) / sizeof(data[0]);
struct HuffmanCode codes[128];
for (int i = 0; i < 128; i++) {
codes[i].data = '\0';
codes[i].code = NULL;
}
huffmanEncode(data, freq, size, codes);
compressData("aaabbbbcccddeeeeffffff", codes, size);
decompressData();
return 0;
}
```
以上代码使用了哈夫曼树的算法对数据进行了压缩,压缩后的数据存储在 `compressed.txt` 文件中,哈夫曼编码存储在 `codes.txt` 文件中,解压缩后的数据存储在 `decompressed.txt` 文件中。
阅读全文