C++基于Huffman编码实现文件压缩和解压

该博客介绍了如何利用C++和Huffman编码实现文件的压缩和解压。首先,读取文本文件计算每个字符的频率,然后生成Huffman树并存储其顺序表示在树信息文件中。在压缩过程中,根据编码对文本进行编码并写入输出文件。解压时,从树信息文件重建Huffman树,依据编码对压缩文件进行解码,最终生成新的文本文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

实验要求

实验目的

利用Huffman编码实现文件的压缩和解压

实验要求

  1. 通过键盘输入原文件路径,对原文件进行压缩操作
  2. 通过键盘输压缩文件路径,对压缩文件进行解压操作

程序思路

压缩文件过程
  1. 读入一个文本文件,计算其中每一个字符出现的次数。
  2. 根据步骤1得到的数据,生成哈夫曼编码树,并得到每种出现字符的具体编码。
  3. 将哈夫曼树存储在树信息文件中。
    要求使用哈夫曼树的顺序表示法存储树的结构(不存储字母的频率信息)
  4. 根据步骤2得到的哈夫曼编码对文本文件进行压缩,并将压缩内容写入输出文件中。
如何将Huffman树存储在树信息文件中

例子
请勿存储节点频率信息,仅需叶节点对应的字母信息即可。
如上图的树结构(先序遍历)可表示为101100101011000对应0的位置即是叶节点的位置,此处仅需存储叶节点的信息(其他信息对解码无用),即各个字母的ASCII码,可按先序遍历的顺序依次存储在树结构后面。第一个int(4个字节),可存储所有节点的个数,便于定位字母的ASCII码的起始位置。

解压文件过程
  1. 读入树信息文件,还原成Huffman树
  2. 读入压缩文件,根据Huffman编码树进行解压
  3. 将步骤2得到的内容写入新的文本文件中

代码

HuffmanCompressAndUn.h

#pragma once
#include <iostream>  
#include <string>  
using namespace std;

//全局变量,重构Huffman树时需要
int leafArrIndex = 0;
int strIndex = 0;
int nodeIndex = 0;

/*Huffman结点*/
class TreeNode {
   
   
public:
	unsigned char it;                            //结点元素                 
	double weight;                              //结点权重
	int parent, lchild, rchild;                 //结点的父结点及左右子结点
	TreeNode() {
   
              
		parent = lchild = rchild = -1; 
	}
	TreeNode(const unsigned char &data, const double &wt) {
   
   
		it = data;
		weight = wt;
		parent = lchild = rchild = -1;
	}
};

/*编码类 存放每个字母的编码*/
class Code {
   
   
public:
	char *ptr;
	const int length;
	Code() : length(20) {
   
    ptr = new char[length]; }
	~Code() {
   
    delete[] ptr; }
};

/*Huffman树*/
class HuffmanTree {
   
   
private:
	int maxSize;                                                                 //数组最大值  
	int findPosition(const unsigned char &) const;          //返回字符在arrayTree[]中的位置 
	void insert(const unsigned char&, const double&);  //插入结点  
	void buildHuffmanTree();                                           //创建哈夫曼树  
	void writeCodeToFile(const char *);                           //将Huffman树存储到树信息文件中   
	void writeTreeStructureToFile(const int &, FILE*);     //将树结构信息存储到树信息文件中
	void writeLeafToFile(const int &, FILE*);                    //将叶结点信息存储到树信息文件中

public:
	int currsize;                   //当前数组大小
	TreeNode *arrayTree;   //哈夫曼结点数组   
	Code *codeArray;         //存放每个叶结点的编码,大小为currsize  

	HuffmanTree() {
   
   
		maxSize = 1000;
		arrayTree = new TreeNode[maxSize];
		currsize = 0;
	}

	void run(const char*, const char*);                                              //编码用,建树 编码 写入树信息文件
	void reBuildHuffmanTree(const unsigned char*, const int*, int); //解码用,根据树信息文件重建Huffman树  
	void createHuffmanCode();                                                         //编解码均可用,创建Huffman编码   
	void reBuildArray(char **, unsigned char *, int);                         //解码用,重建结点数组
};

/*run函数的实现*/
void HuffmanTree::run(const char *inFilename, const char *outFilename) {
   
   
	FILE *fo;
	fopen_s(&fo, inFilename, "rb");                        //读入待压缩文件  读取二进制文件
	if (fo == NULL) {
   
   
		cerr << " Can not open!" << endl;
		exit(1);
	}
	unsigned char ch = fgetc(fo);                           //读取一个字符
	int pos;

	while (!feof(fo)) {
   
                                                 // 从文件当中读入字符 直到文件结束,并且统计字符个数
		pos = findPosition(ch);
		if (pos != -1)
			arrayTree[pos].weight++;
		else
			insert(ch, 1);                                             //新插入一个 权重为1
		ch = fgetc(fo);
	}
	buildHuffmanTree();                   //构造huffman树  
	createHuffmanCode();               //对统计字符进行编码  
	writeCodeToFile(outFilename); //将编码表存入文件  
	fclose(fo);
}

/*插入结
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值