c语言 huffman编码解码
时间: 2023-07-09 21:10:01 浏览: 66
Huffman编码是一种无损压缩算法,常用于数据传输和存储中。下面是C语言实现Huffman编码和解码的基本思路:
Huffman编码:
1. 统计字符出现频率,构建字符频率表;
2. 将字符频率表中的字符和频率信息构建成一棵Huffman树;
3. 遍历Huffman树,给每个字符生成对应的Huffman编码;
4. 将编码写入文件。
Huffman解码:
1. 读取压缩文件中的编码信息和字符频率表;
2. 根据字符频率表构建Huffman树;
3. 遍历Huffman树,根据编码信息还原原始字符串。
以下是C语言实现Huffman编码和解码的参考代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_TREE_HT 100
// Huffman树节点结构体
struct MinHeapNode {
char data;
unsigned freq;
struct MinHeapNode *left, *right;
};
// Huffman编码表结构体
struct HuffmanCode {
char data;
char *code;
};
// 最小优先队列结构体
struct MinHeap {
unsigned size;
unsigned capacity;
struct MinHeapNode **array;
};
// 创建一个新的Huffman树节点
struct MinHeapNode* newNode(char data, unsigned freq)
{
struct MinHeapNode* node = (struct MinHeapNode*)malloc(sizeof(struct MinHeapNode));
node->left = node->right = NULL;
node->data = data;
node->freq = freq;
return node;
}
// 创建一个最小优先队列
struct MinHeap* createMinHeap(unsigned capacity)
{
struct MinHeap* minHeap = (struct MinHeap*)malloc(sizeof(struct MinHeap));
minHeap->size = 0;
minHeap->capacity = capacity;
minHeap->array = (struct MinHeapNode**)malloc(minHeap->capacity * sizeof(struct MinHeapNode*));
return minHeap;
}
// 交换两个节点
void swapMinHeapNode(struct MinHeapNode** a, struct MinHeapNode** b)
{
struct MinHeapNode* t = *a;
*a = *b;
*b = t;
}
// 最小堆化
void minHeapify(struct MinHeap* minHeap, int idx)
{
int smallest = idx;
int left = 2 * idx + 1;
int right = 2 * idx + 2;
if (left < minHeap->size && minHeap->array[left]->freq < minHeap->array[smallest]->freq)
smallest = left;
if (right < minHeap->size && minHeap->array[right]->freq < minHeap->array[smallest]->freq)
smallest = right;
if (smallest != idx) {
swapMinHeapNode(&minHeap->array[smallest], &minHeap->array[idx]);
minHeapify(minHeap, smallest);
}
}
// 检查堆大小是否为1
int isSizeOne(struct MinHeap* minHeap)
{
return (minHeap->size == 1);
}
// 取出堆顶元素
struct MinHeapNode* extractMin(struct MinHeap* minHeap)
{
struct MinHeapNode* temp = minHeap->array[0];
minHeap->array[0] = minHeap->array[minHeap->size - 1];
--minHeap->size;
minHeapify(minHeap, 0);
return temp;
}
// 插入新的节点
void insertMinHeap(struct MinHeap* minHeap, struct MinHeapNode* minHeapNode)
{
++minHeap->size;
int i = minHeap->size - 1;
while (i && minHeapNode->freq < minHeap->array[(i - 1) / 2]->freq) {
minHeap->array[i] = minHeap->array[(i - 1) / 2];
i = (i - 1) / 2;
}
minHeap->array[i] = minHeapNode;
}
// 构建最小优先队列
void buildMinHeap(struct MinHeap* minHeap)
{
int n = minHeap->size - 1;
int i;
for (i = (n - 1) / 2; i >= 0; --i)
minHeapify(minHeap, i);
}
// 判断是否是叶子节点
int isLeaf(struct MinHeapNode* root)
{
return !(root->left) && !(root->right);
}
// 创建一个最小优先队列并构建Huffman树
struct MinHeap* createAndBuildMinHeap(char data[], int freq[], int size)
{
int i;
struct MinHeap* minHeap = createMinHeap(size);
for (i = 0; i < size; ++i)
minHeap->array[i] = newNode(data[i], freq[i]);
minHeap->size = size;
buildMinHeap(minHeap);
return minHeap;
}
// 构建Huffman树
struct MinHeapNode* buildHuffmanTree(char data[], int freq[], int size)
{
struct MinHeapNode *left, *right, *top;
struct MinHeap* minHeap = createAndBuildMinHeap(data, freq, size);
while (!isSizeOne(minHeap)) {
left = extractMin(minHeap);
right = extractMin(minHeap);
top = newNode('$', left->freq + right->freq);
top->left = left;
top->right = right;
insertMinHeap(minHeap, top);
}
return extractMin(minHeap);
}
// 生成Huffman编码
void generateCodes(struct MinHeapNode* root, char *code, int top, struct HuffmanCode *huffmanCode)
{
if (root->left) {
code[top] = '0';
generateCodes(root->left, code, top + 1, huffmanCode);
}
if (root->right) {
code[top] = '1';
generateCodes(root->right, code, top + 1, huffmanCode);
}
if (isLeaf(root)) {
huffmanCode[root->data].data = root->data;
huffmanCode[root->data].code = (char*)malloc((top + 1) * sizeof(char));
memcpy(huffmanCode[root->data].code, code, (top + 1) * sizeof(char));
}
}
// 打印Huffman编码表
void printHuffmanCodes(struct HuffmanCode *huffmanCode, int size)
{
int i;
printf("Huffman编码表:\n");
for (i = 0; i < size; ++i)
printf("%c: %s\n", huffmanCode[i].data, huffmanCode[i].code);
}
// 压缩文件
void compressFile(char *fileName, struct HuffmanCode *huffmanCode, int size)
{
FILE *fpIn, *fpOut;
char ch, *code;
int i, j, len;
fpIn = fopen(fileName, "r");
if (fpIn == NULL) {
printf("打开文件失败!\n");
return;
}
fpOut = fopen("compressed.dat", "wb");
fwrite(&size, sizeof(int), 1, fpOut);
for (i = 0; i < size; ++i) {
fwrite(&huffmanCode[i].data, sizeof(char), 1, fpOut);
len = strlen(huffmanCode[i].code);
fwrite(&len, sizeof(int), 1, fpOut);
fwrite(huffmanCode[i].code, sizeof(char), len, fpOut);
}
code = (char*)malloc(MAX_TREE_HT * sizeof(char));
while ((ch = fgetc(fpIn)) != EOF) {
for (i = 0; i < size; ++i) {
if (huffmanCode[i].data == ch) {
len = strlen(huffmanCode[i].code);
for (j = 0; j < len; ++j)
code[j] = huffmanCode[i].code[j];
fwrite(code, sizeof(char), len, fpOut);
break;
}
}
}
fclose(fpIn);
fclose(fpOut);
printf("压缩成功!\n");
}
// 解压文件
void decompressFile(char *fileName)
{
FILE *fpIn, *fpOut;
struct HuffmanCode huffmanCode[256];
char ch, *code;
int i, j, len, size;
fpIn = fopen(fileName, "rb");
if (fpIn == NULL) {
printf("打开文件失败!\n");
return;
}
fpOut = fopen("decompressed.txt", "w");
fread(&size, sizeof(int), 1, fpIn);
for (i = 0; i < size; ++i) {
fread(&huffmanCode[i].data, sizeof(char), 1, fpIn);
fread(&len, sizeof(int), 1, fpIn);
huffmanCode[i].code = (char*)malloc((len + 1) * sizeof(char));
fread(huffmanCode[i].code, sizeof(char), len, fpIn);
huffmanCode[i].code[len] = '\0';
}
code = (char*)malloc(MAX_TREE_HT * sizeof(char));
struct MinHeapNode *root = buildHuffmanTree(NULL, NULL, 0);
struct MinHeapNode *curr = root;
while ((ch = fgetc(fpIn)) != EOF) {
for (i = 0; i < 8; ++i) {
if (ch & (1 << (7 - i))) // ASCII码从高位开始读
curr = curr->right;
else
curr = curr->left;
if (isLeaf(curr)) {
fputc(curr->data, fpOut);
curr = root;
}
}
}
fclose(fpIn);
fclose(fpOut);
printf("解压成功!\n");
}
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 huffmanCode[256];
struct MinHeapNode* root = buildHuffmanTree(data, freq, size);
char code[MAX_TREE_HT];
int top = 0;
generateCodes(root, code, top, huffmanCode);
printHuffmanCodes(huffmanCode, size);
compressFile("input.txt", huffmanCode, size);
decompressFile("compressed.dat");
return 0;
}
```
上述代码中,我们使用了最小优先队列来构建Huffman树。在生成Huffman编码时,我们使用了递归的方法遍历树,并记录下每个叶子节点的编码。在压缩文件时,我们将字符的Huffman编码写入输出文件中。在解压文件时,我们读取压缩文件中的编码信息和字符频率表,根据它们构建Huffman树,并根据编码信息还原原始字符串。
相关推荐
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)