数据结构实训之——哈夫曼树压缩文件和解压文件(C语言)

实训目的

这次实训是我在大学第一次实训啊哈哈哈哈,这次实训也让我对与哈夫曼压缩和解压缩这方面的应用有了很大的理解和提升
这次实训的目的如下:
这次我们的实训搞得东西还挺多的,比如不是简单的压缩了,当然了移位的压缩也有哈,多了一个还要将其哈夫曼编码文件每八个字符转换成十六进制再压缩,具体的实训要求看下图:
在这里插入图片描述

代码

代码方面比较长,总共是1000行左右,所以捏在这里就不太好放出来了,太长了,想要源码还要word文档(里面有我的思路和我的一些想法,恳请指教)的朋友可以私聊我或者评论区找我,我看到会第一时间回复大家哒哒哒哒,那下面就先展示了实验的最终结果:

实验部分截图

在这里插入图片描述

在这里插入图片描述

目标文件:
在这里插入图片描述
压缩之后:
在这里插入图片描述

可以看到压缩效果还是不错的,由于这只是测试用例,所以大家就暂且看一下效果哈

解压缩之后的文件:(还原)
在这里插入图片描述

就暂时给大家看到这里啦,有兴趣的私聊我看源码吧
在这里插入图片描述

心里话♥

虽然这只是一次不是很大的项目,只是一个实训,但是这次实训给了我特别多的想法,代码里很多东西真的不是说说那么简单,很多东西要真正去实现的时候,你亲自在你的编译器上打的时候才知道,噢原来是我想的太简单了,我喜欢这种感觉,这让我重新正视它,重新解读它,我希望这种感觉可以伴我余生,无论我以后是否从事计算机方面的行业,但这种感觉,it roll me up,get me high,so just move the fuck on!
欢迎评论和交流!
在这里插入图片描述

源码+实验报告😋

私聊我~🍦

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
以下是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; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是X大魔王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值