c语言哈夫曼压缩及解压
时间: 2023-11-24 13:03:16 浏览: 105
哈夫曼压缩是一种常用的数据压缩算法,可以有效地减少数据文件的大小。在C语言中,可以通过实现哈夫曼编码和解码来实现数据的压缩和解压。
首先,实现哈夫曼编码,需要构建哈夫曼树和编码表。可以通过使用优先队列来构建哈夫曼树,然后通过递归的方式生成每个字符对应的哈夫曼编码。在C语言中,可以使用结构体来表示哈夫曼树节点,并使用数组来表示编码表。
接着,利用生成的编码表来将原始数据进行编码。对于每个字符,根据编码表找到对应的哈夫曼编码,并将其写入到输出文件中。这样就实现了数据的压缩。
解压的过程与压缩相反,首先需要读取压缩文件中的编码表和编码后的数据。然后根据编码表和哈夫曼树来对数据进行解码,将其还原为原始的字符序列。
在C语言中,可以通过使用文件操作函数来读写文件,以及使用动态内存分配函数来构建哈夫曼树和编码表。通过合理设计数据结构和使用适当的算法,可以有效地实现哈夫曼压缩和解压。
总之,通过在C语言中实现哈夫曼编码和解码,可以实现数据的高效压缩和解压,从而节省存储空间和提高数据传输效率。
相关问题
c语言哈夫曼树压缩解压文件
以下是C语言实现哈夫曼树压缩解压文件的步骤和代码示例:
1. 定义哈夫曼树节点结构体和哈夫曼编码表结构体
```c
typedef struct {
unsigned int weight; // 字符权重
unsigned int parent, lchild, rchild; // 父节点、左子节点、右子节点
} HTNode, *HuffmanTree;
typedef char** HuffmanCode; // 动态分配数组存储哈夫曼编码表
```
2. 定义哈夫曼树相关函数
```c
// 选择权值最小的两个节点
void select(HuffmanTree HT, int n, int* s1, int* s2);
// 建立哈夫曼树
void createHuffmanTree(HuffmanTree* HT, int n);
// 生成哈夫曼编码
void createHuffmanCode(HuffmanTree HT, HuffmanCode* HC, int n);
// 压缩文件
void compressFile(char* inputFile, char* outputFile, HuffmanCode HC);
// 解压文件
void decompressFile(char* inputFile, char* outputFile, HuffmanTree HT, int fileLength);
```
3. 实现哈夫曼树相关函数
```c
// 选择权值最小的两个节点
void select(HuffmanTree HT, int n, int* s1, int* s2) {
int i;
unsigned int min1 = UINT_MAX, min2 = UINT_MAX; // 初始化为最大值
for (i = 1; i <= n; i++) {
if (HT[i].parent == 0) { // 只考虑未被选中的节点
if (HT[i].weight < min1) {
min2 = min1;
*s2 = *s1;
min1 = HT[i].weight;
*s1 = i;
}
else if (HT[i].weight < min2) {
min2 = HT[i].weight;
*s2 = i;
}
}
}
}
// 建立哈夫曼树
void createHuffmanTree(HuffmanTree* HT, int n) {
if (n <= 1) {
return;
}
int m = 2 * n - 1; // 哈夫曼树总节点数
*HT = (HuffmanTree)malloc((m + 1) * sizeof(HTNode)); // 动态分配数组存储哈夫曼树
int i;
for (i = 1; i <= n; i++) { // 初始化前n个节点
(*HT)[i].weight = 0;
(*HT)[i].parent = 0;
(*HT)[i].lchild = 0;
(*HT)[i].rchild = 0;
}
for (i = n + 1; i <= m; i++) { // 初始化后m-n个节点
(*HT)[i].weight = 0;
(*HT)[i].parent = 0;
(*HT)[i].lchild = 0;
(*HT)[i].rchild = 0;
}
for (i = 1; i <= n; i++) { // 输入前n个节点的权值
scanf("%d", &((*HT)[i].weight));
}
int s1, s2;
for (i = n + 1; i <= m; i++) { // 构造哈夫曼树
select(*HT, i - 1, &s1, &s2);
(*HT)[s1].parent = i;
(*HT)[s2].parent = i;
(*HT)[i].lchild = s1;
(*HT)[i].rchild = s2;
(*HT)[i].weight = (*HT)[s1].weight + (*HT)[s2].weight;
}
}
// 生成哈夫曼编码
void createHuffmanCode(HuffmanTree HT, HuffmanCode* HC, int n) {
*HC = (HuffmanCode)malloc((n + 1) * sizeof(char*)); // 动态分配数组存储哈夫曼编码表
char* code = (char*)malloc(n * sizeof(char)); // 分配临时存储编码的空间
code[n - 1] = '\0'; // 编码结束符
int i;
for (i = 1; i <= n; i++) { // 逐个字符求哈夫曼编码
int start = n - 1; // 编码结束符位置
int c = i; // 从叶子节点开始向上回溯
int f = HT[i].parent;
while (f != 0) { // 直到回溯到根节点
if (HT[f].lchild == c) {
code[--start] = '0';
}
else {
code[--start] = '1';
}
c = f;
f = HT[f].parent;
}
(*HC)[i] = (char*)malloc((n - start) * sizeof(char)); // 分配存储编码的空间
strcpy((*HC)[i], &code[start]); // 复制编码
}
free(code); // 释放临时存储编码的空间
}
// 压缩文件
void compressFile(char* inputFile, char* outputFile, HuffmanCode HC) {
FILE* in = fopen(inputFile, "rb"); // 以二进制方式打开输入文件
FILE* out = fopen(outputFile, "wb"); // 以二进制方式打开输出文件
unsigned char c; // 读入的字符
unsigned char buffer = 0; // 缓存区
int count = 0; // 缓存区中剩余的位数
while (fread(&c, sizeof(unsigned char), 1, in) == 1) { // 逐个字符读入
char* code = HC[c]; // 获取哈夫曼编码
while (*code != '\0') { // 逐位写入缓存区
if (*code == '1') {
buffer = buffer | (1 << count);
}
count++;
if (count == 8) { // 缓存区满了,写入输出文件
fwrite(&buffer, sizeof(unsigned char), 1, out);
buffer = 0;
count = 0;
}
code++;
}
}
if (count > 0) { // 最后一个字节不足8位,补0写入输出文件
buffer = buffer << (8 - count);
fwrite(&buffer, sizeof(unsigned char), 1, out);
}
fclose(in); // 关闭输入文件
fclose(out); // 关闭输出文件
}
// 解压文件
void decompressFile(char* inputFile, char* outputFile, HuffmanTree HT, int fileLength) {
FILE* in = fopen(inputFile, "rb"); // 以二进制方式打开输入文件
FILE* out = fopen(outputFile, "wb"); // 以二进制方式打开输出文件
unsigned char c; // 读入的字符
int p = 2 * fileLength - 1; // 指向哈夫曼树根节点
while (fread(&c, sizeof(unsigned char), 1, in) == 1) { // 逐个字节读入
int i;
for (i = 0; i < 8; i++) { // 逐位解码
if ((c & (1 << (7 - i))) == 0) {
p = HT[p].lchild;
}
else {
p = HT[p].rchild;
}
if (HT[p].lchild == 0 && HT[p].rchild == 0) { // 到达叶子节点,写入输出文件
fwrite(&(HT[p].weight), sizeof(unsigned char), 1, out);
p = 2 * fileLength - 1; // 指向哈夫曼树根节点
}
}
}
fclose(in); // 关闭输入文件
fclose(out); // 关闭输出文件
}
```
4. 调用函数进行压缩解压文件
```c
int main() {
HuffmanTree HT;
HuffmanCode HC;
int n = 256; // 字符集大小
createHuffmanTree(&HT, n); // 建立哈夫曼树
createHuffmanCode(HT, &HC, n); // 生成哈夫曼编码
compressFile("input.txt", "output.dat", HC); // 压缩文件
decompressFile("output.dat", "output.txt", HT, n); // 解压文件
return 0;
}
```
c语言哈夫曼编码压缩文件
C语言实现哈夫曼编码压缩文件的过程可以分为以下几个步骤:
1. 统计字符频率:从输入的文本文件中读取字符,并统计每个字符出现的频率。
2. 构建哈夫曼树:根据字符频率构建哈夫曼树。哈夫曼树是一种最优二叉树,其中频率较低的字符位于树的较低层,频率较高的字符位于树的较高层。
3. 生成哈夫曼编码表:通过遍历哈夫曼树,为每个字符生成对应的哈夫曼编码。哈夫曼编码是由0和1组成的二进制编码,用于表示每个字符。
4. 压缩文件:将输入的文本文件中的字符根据哈夫曼编码表进行编码,并将编码后的二进制数据写入输出文件。这样可以实现对文本文件的压缩。
5. 计算压缩率:通过比较压缩后的文件大小与原始文件大小,计算出压缩率。压缩率越高,表示压缩效果越好。
6. 解压文件:读取压缩文件中的二进制数据,并根据哈夫曼编码表进行解码,将解码后的字符写入输出文件。这样可以实现对压缩文件的解压缩。
以下是一个C语言实现哈夫曼编码压缩文件的示例代码:
```c
// 哈夫曼树节点结构体
typedef struct Node {
char data; // 字符
int freq; // 频率
struct Node* left;
struct Node* right;
} Node;
// 构建哈夫曼树
Node* buildHuffmanTree(char* text);
// 生成哈夫曼编码表
void generateHuffmanCodes(Node* root, char* code, int depth, char** codes);
// 压缩文件
void compressFile(char* inputFile, char* outputFile, char** codes);
// 解压文件
void decompressFile(char* inputFile, char* outputFile, Node* root);
// 计算文件大小
long getFileSize(FILE* file);
// 计算压缩率
float calculateCompressionRatio(long originalSize, long compressedSize);
int main() {
char* inputFile = "input.txt";
char* compressedFile = "compressed.bin";
char* decompressedFile = "decompressed.txt";
// 构建哈夫曼树
Node* root = buildHuffmanTree(inputFile);
// 生成哈夫曼编码表
char* codes[256];
generateHuffmanCodes(root, "", 0, codes);
// 压缩文件
compressFile(inputFile, compressedFile, codes);
// 解压文件
decompressFile(compressedFile, decompressedFile, root);
// 计算文件大小和压缩率
FILE* inputFilePtr = fopen(inputFile, "rb");
FILE* compressedFilePtr = fopen(compressedFile, "rb");
long originalSize = getFileSize(inputFilePtr);
long compressedSize = getFileSize(compressedFilePtr);
float compressionRatio = calculateCompressionRatio(originalSize, compressedSize);
printf("Compression ratio: %.2f%%\n", compressionRatio);
// 释放内存
// ...
return 0;
}
```
阅读全文
相关推荐













