数据结构的作业,压缩软件用的,具体写的过程中有哪些问题在程序里说吧。
头文件与常量部分:
利用char的8位,来存储文件里的元素。每次取出文件中的8位并记录这八位出现的次数用来进行哈夫曼数的建立。
#include<iostream>
#include<stack>
#include<string>
#include<list>
#include<iterator>
using namespace std;
//利用char进行8位一取,这样不管是字符类型还是汉字或者其他格式都可以进行压缩
const unsigned int N = 256;//char共有8位,那么一共最多有256个可能的字符,叶节点数目
const unsigned int M = 2 * N;//对于拥有n个叶结点的huffman树,一共有2*n-1个结点,数组最后一位不存数,供select函数选择使用
const unsigned long long MAX = 0xffffffffffff;
三个类的声明部分:
Buffer类用来从文件中读取8位字符或者写入8位字符。因为每次都只能从文件中读取或者写入一个字符,所以利用Buffer类进行缓冲。
treeNode类是哈夫曼树的结点类,其中保存了树中每个结点出现的频率与其左右子结点与父节点。
HuffmanTree类是哈夫曼树类,可以进行压缩或解压。
class Buffer {//缓冲类,对文件进行读取/写入操作的时候通过Buffer类进行整个字符的读取/写入
public:
unsigned int bits;//实际字节长度
char ch;//字节
};
class HuffmanTree;//huffman树类声明
class treeNode {//huffman树结点类
friend HuffmanTree;
private:
unsigned long long weight;//该结点一共出现了多少次
unsigned int right, left;
unsigned int parents;
};
class HuffmanTree {//huffman树类
private:
treeNode nodes[M];//存储树的每个结点信息,最多M个
unsigned int leaf[N];//存储叶节点字符信息,最多N个
unsigned int index[N];//存储叶节点的下标值
char* leafCode[N];//存储叶节点的编码信息
FILE* input, *output;
unsigned int num;//实际上叶结点个数
unsigned long long size;//一共有多少个字符
Buffer buf;//输入输出缓冲
//辅助函数
void write(unsigned int i);//向文件中写入一个bite
void write(unsigned int num, unsigned int bits);//向文件中写入bits位的num数
void writerest();//如果最后buf里面还有字符没有写入,用这个函数一起写入
void read(unsigned int &i);//从文件中读取一位bite,用i输出
void read(unsigned int &num, unsigned int bits);//从文件中读取bits位的数,并用num输出
//Encode辅助函数
void enSieve();//读取文件,并且统计文件中字符数
void select(unsigned int pos,unsigned int &t1,unsigned int &t2);//在0——pos间选择两个权重最小的,用t1、t2输出
void enSetTree();//对需要被压缩的文件中的字符建立huffman树,并且完善每个结点的编码信息
//Decode辅助函数
void deSieve();//读取需要被解压文件,并建造其哈夫曼树
public:
void Encode();//对文件编码
void Decode();//对文件译码
};
HuffmanTree类的实现:
读取/写入辅助函数:
主要是利用Buffer类中的bits来记录ch中实际有效的位数。在write的时候,如果ch中实际位数已经足够8位,那么将ch写入文件,然后再将bits置8,ch置0;在read的时候,如果ch的实际位数已经等于0,那么从文件中fget()一个8位数给ch,同时bits置8。同时,有可能在写入到最后的时候,bits实际上并不等于0,那么用writerest将剩下的ch全部写入。
//辅助函数块
void HuffmanTree::write(unsigned int i) {//向文件中写入一个bite
buf.ch = (buf.ch << 1) + i;//对ch加上一位
buf.bits++;//ch的八位bite的实际使用量加一
if (buf.bits == 8) {//如果全部用完,那么将buf.ch输入进output中,并将buf.bits,buf.ch置0重新开始新一轮计数
fputc(buf.ch, output);
buf.bits = 0;
buf.ch = 0;
}
}
void HuffmanT