文件压缩与解压实验报告

合集下载

《C语言课程设计》实验报告-RLE压缩解压算法

《C语言课程设计》实验报告-RLE压缩解压算法

《C语言课程设计》实验报告一、问题描述题目4:RLE压缩解压算法涉及知识点:文件读写、位操作、内存管理、结构体定义、RLE算法、命令行参数要求:编写一个程序,可以在命令行输入参数,完成指定文件的压缩解压命令行参数如下rle file1 –c(-d) file2第一个参数为可执行程序名称,第二个参数为原始文件名,第三个参数为压缩或解压缩选项,第四个参数为新文件名说明:通过该练习,学生需要掌握:(1)文件操作(2)位操作(3)RLE算法(相关算法可以查阅资料,我们这里要求数据都是1个字节作为单位长度的)二、技术关键点分析1.读取原始文件FILE* f1;FILE* f2;f1 = fopen(argv[1], "rb");if(f1 == NULL){printf("找不到这文件!\n");return0;}int t = 0;int a = 0;//读取文件while ((a = fgetc(f1)) != EOF) {file_src[t++] = a;}f2 = fopen(argv[3], "wb");int size = t;printf("输入字符数%d",size);2.选择解码还是编码if( strcmp(argv[2], "-d") == 0){size = RLEdecode(file_src, size, file_dst, MAX_CHAR);printf("输出字符数%d",size);}else if(strcmp(argv[2], "-e") == 0){size = RLEencode(file_src, size, file_dst, MAX_CHAR);printf("输出字符数%d",size);}3(1)解码//RLE 解码算法,正好是编码算法的反过程int RLEdecode(unsigned char* src,int src_len,unsigned char* dst,int dst_len){unsigned char *data = src;int left = src_len;int point = 0;//输出缓冲区指针while(data < src + src_len){unsigned char zifu = *data++;int count = zifu & 0x7f;//请注意,一定要注意,这里是巨大bug易发生地,因为==的优先级其实比&要高,一定要加括号,一定要注意if((zifu&0x80)==0x80)//是重复字符{for(int i=0;i<count;i++){dst[point++] = *data;}data++;}else{for(int i=0;i<count;i++){dst[point++] = *data++;}}}return point;}3(2)编码//RLE算法,编码,输入参数为源数组,源数组长度,目标数组,目标数组长度int RLEencode(unsigned char* src,int src_len,unsigned char* dst,int dst_len){unsigned char *data = src;int left = src_len;int point = 0;//输出缓冲区指针while(left > 0){int count = 0;if(Isrepeat(data,left)){count =getrepeatlength(data,left);dst[point++] = count|0x80;//写重复数据的数据量dst[point++] = *data;//写字符//指针移动data+=count;left-=count;}else{count =getnorepeatlength(data,left);dst[point++] = count;for(int i=0;i<count;i++){dst[point++] = *data;data++;}left-=count;}}return point;}int Isrepeat(unsigned char* src,int left){if(left<3)////判断是否是重复数据,注意,只有重复数据大于3的时候才被判定为i重复数据{return0;}if(src[0] == src[1]&&src[1] == src[2]){return1;}return0;}//获得重复数据的长度int getrepeatlength(unsigned char* src,int left){unsigned char data = src[0];int len = 1;while(len<left&&len<127&&src[len] == data){len++;}return len;}//获得不重复数据的长度int getnorepeatlength(unsigned char* src,int left){if(left < 3)return left;//不重复数据的长度至少为2int len = 2;//first和second代表前后两个字符,不断向后移动unsigned char first = src[0];unsigned char second = src[1];while(len<left&&len<127){if(!(first==second&&src[len]==second)){first = second;second = src[len];len++;}else{break;}}return len;}4.关闭文件fwrite(file_dst, size, sizeof(unsigned char), f2);fclose(f1);fclose(f2);三、流程图四、测试与分析解压缩。

文件压缩与解压实验报告

文件压缩与解压实验报告

院系:计算机学院实验课程:实验3实验项目:文本压缩与解压指导老师:开课时间:2010 ~ 2011年度第 1学期专业:班级:学生:学号:一、需求分析1.本程序能够实现将一段由大写字母组成的内容转为哈弗曼编码的编码功能以及将哈弗曼编码翻译为字符的译码功能。

2.友好的图形用户界面,直观明了,每一个操作都有相应的提示,用户只需按着提示去做,便能轻松实现编码以及译码的效果,编码及译码结果都被保存成txt 文档格式,方便用户查看。

3.本程序拥有极大的提升空间,虽然现在只能实现对大写字母的译码以及编码,但通过改进鉴别的算法,即能够实现小写字母乃至其他特殊符号等的编码。

4.本程序可用于加密、解密,压缩后文本的大小将被减小,更方便传输5.程序的执行命令包括:1)初始化 2)编码 3)译码 4)印代码文件 5)印哈弗曼树 6)退出6.测试数据(1)THIS PROGRAM IS MY FAVOURITE(2)THIS IS MY FAVOURITE PROGRAMBUT THE REPORT IS NOT二、概要设计为实现上述功能,应有哈弗曼结点,故需要一个抽象数据类型。

1.哈弗曼结点抽象数据类型定义为:ADT HaffTree{数据对象:HaffNode* ht,HaffCode* hc基本操作:Haffman(int w[],int n)操作结果:构造哈弗曼树及哈弗曼编码,字符集权值存在数组w,大小为nsetdep()setdep(int p,int l)操作结果:利用递归,p为哈弗曼节点序号,l为哈弗曼节点深度setloc()操作结果:设置哈弗曼节点坐标,用以输出到界面setloc2()操作结果:设置哈弗曼节点坐标,用以输出到文本,默认状态下不启用} ADT HaffTree2.本程序包含4个模块1)主程序模块:接受用户要求,分别选择执行①初始化②编码③译码④印代码文件⑤印哈弗曼树⑥退出2)哈弗曼树单元模块——建立哈弗曼树3)哈弗曼编码单元模块——进行哈弗曼编码、译码4)响应用户操作,输出内容到界面或文本各模块之间的关系如下:三、详细设计1.全局变量、结点int m_gcharnum;弗曼树的实现eight=w[i];elseht[i].weight=0;arent=0;child=-1;child=-1;eight<m1&&ht[j].parent==0)ei ght;x1=j;}else if(ht[j].weight<m2&&ht[j].parent==0)eight;x2=j;}}ht[x1].parent=n+i;ht[x2].parent=n+i;ht[n+i].weight=ht[x1].weight+ht[x2].weight;ht[n+i].lchild=x1;ht[ht[n+i].lchild].k=0;child=x2;ht[ht[n+i].rchild].k=1;eight;child=i;parent=ht[child].parent;while(parent!=0)child==child)[]=0;else[]=1;;child=parent;parent=ht[child].parent;}for(j=+1;j<n;j++){ hc[i].bit[j]=[j];}tart=;hc[i].weight=;}}3.主函数和其他函数的实现1)哈弗曼树类的成员函数的实现:child,l+1);ht[p].dep=l;setdep(ht[p].rchild,l+1);}}child;=x+f*10;ht[k].y=ht[k].dep*30;}i=ht[k].rchild;n=1024;=-1;ep)==0)n=ht[ht[p].parent].sn-1024/pow(2 ,ht[p].dep-1);}if(ht[p].k==1)n=ht[ht[p].parent].sn+1024/pow(2,ht[p].dep-1);}();}else{ ();}if(ht[p].lchild!=-1){ (ht[p].lchild);}child!=-1){(ht[p].rchild);}child;);,[k].y,str);child;child!=-1){pDC->MoveTo[k].x+4,[k].y);pDC->LineTo[[k].lchild].x+4,[[k].lchild].y);}if[k].rchild!=-1){pDC->MoveTo[k].x+4,[k].y);pDC->LineTo[[k].rchild].x+4,[[k].rchild].y);}<<endl;eight<<endl;arent<<endl;child<<endl;child<<endl;=" ";}else{fip>>c;[i].s=c;}fip>>w[i];arent;child;child;xt)|*.txt|所有文件(*.*)|*.*|"),NULL);if() == IDOK){m_path1 = ();xt)|*.txt|所有文件(*.*)|*.*|"),NULL);if() == IDOK){m_path2 = ();UpdateData(FALSE);}ofstream sff(m_path2);i++;}for(j=[i].start+1;j<m_gcharnum;j++)sff<<[i].bit[j];xt)|*.txt|所有文件(*.*)|*.*|"),NULL);if() == IDOK){m_path1 = ();UpdateData(FALSE);}AfxMessageBox("译码成功,请保存!");CFileDialog hFileDlg1(false,NULL,NULL,OFN_FILEMUSTEXIST | OFN_READONLY | OFN_PATHMUSTEXIST,TEXT("文档文本 (*.txt)|*.txt|所有文件(*.*)|*.*|"),NULL);if() == IDOK){m_path2 = ();UpdateData(FALSE);}ifstream ldf(m_path1);child;}if(c=='0')child;}if[i].lchild==-1&&[i].rchild==-1);i=2*m_gcharnum-2;}}}}();();}else{AfxMessageBox("您尚未执行初始化操作!请先执行初始化操作!");}}xt)|*.txt|所有文件(*.*)|*.*|"),NULL);if() == IDOK){m_path = ();UpdateData(FALSE);}ofstream saf(m_path);/*();n;}else{ d++;break;}if(d==[p].dep){for(t1;t1<t2-1;t1++) { saf<<" ";}if[p].s==" "||[p].s=="")saf<<"0";;child!=-1)[p].lchild);if(ht[p].rchild!=-1)[p].rchild);t1+=2;}else{d++;saf<<endl;t1=0;t2=0;}}}child;ep-1);f++) saf<<" ";<<endl;child;"");CString str1;GetDlgItemText(IDC_EDIT1,str1);xt)|*.txt|所有文件(*.*)|*.*|"),NULL);if() == IDOK){m_path = ();UpdateData(FALSE);}CFile file1( m_path,CFile::modeRead);char *pBuf;int iLen=();pBuf =new char[iLen+1];(pBuf,iLen);pBuf[iLen]=0;();SetDlgItemText(IDC_EDIT1,pBuf);}xt)|*.txt|所有文件(*.*)|*.*|"),NULL);if() == IDOK){m_path = ();UpdateData(FALSE);}CFile file;(m_path,CFile::modeCreate|CFile::modeWrite);CString strValue;GetDlgItemText(IDC_EDIT1,strValue);xt)|*.txt|所有文件(*.*)|*.*|"),NULL);AfxMessageBox("请选择刚才输入的内容所要保存到的位置!");if() == IDOK){m_path = ();UpdateData(FALSE);}CFile file;(m_path,CFile::modeCreate|CFile::modeWrite);CString strValue;GetDlgItemText(IDC_EDIT1,strValue);xt)|*.txt|所有文件(*.*)|*.*|"),NULL);if() == IDOK){m_path2 = ();UpdateData(FALSE);}ifstream ldf(m_path,ios::in);i++;}for(j=[i].start+1;j<m_gcharnum;j++) sff<<[i].bit[j];}}AfxMessageBox("代码文件已保存成功!");CDialog::OnOK();}4.函数的调用关系图反映了演示程序的层次结构Main(主窗口、主文档)初始化OnHandinput OnAutoget编码OnEncodinghinputOnEncodingainput译码OnDecoding印代码文件OnPte印哈弗曼树OnPhafftreeHaffman Setdep setloc四、调试分析1.由于一开始时候编写的时候没有注意使用面向对象的思想,并没有建立哈弗曼树类,程序完成后才将其转为面向对象的方式,修改仓促,因而使得哈弗曼树类丧失了封装性。

压缩实验报告数据分析

压缩实验报告数据分析

压缩实验报告数据分析1. 引言本文对压缩实验的数据进行了分析和总结。

压缩是一种常见的数据处理技术,通过减少文件的大小,可以提高存储和传输效率。

本实验旨在探究不同压缩算法对不同类型的数据的效果以及压缩率的变化情况。

2. 数据收集和实验设计在本实验中,我们收集了不同类型的数据文件,包括文本文件、图像文件和音频文件。

我们选择了三种常用的压缩算法,分别是gzip、zip和tar。

每个数据文件都分别用这三种算法进行了压缩,并记录了压缩前后的文件大小。

实验设计如下: - 数据收集:从不同来源收集文本、图像和音频文件。

- 压缩算法选择:选择gzip、zip和tar作为压缩算法。

- 压缩实验:分别使用这三种压缩算法对每个数据文件进行压缩。

- 数据记录:记录每个文件的原始大小和压缩后的大小。

3. 数据分析3.1 压缩率分析首先,我们对每个数据文件进行了压缩率的计算。

压缩率表示压缩后文件大小与原始文件大小的比值,可以反映出压缩算法的效果。

表格1:不同数据文件的压缩率文件名gzip压缩率zip压缩率tar压缩率文本文件0.4 0.3 0.35图像文件0.6 0.5 0.55音频文件0.2 0.15 0.18从表格1中可以看出,不同类型的数据文件在不同的压缩算法下的压缩率有所不同。

图像文件的压缩率相对较高,而音频文件的压缩率相对较低。

3.2 压缩算法效果比较接下来,我们对不同压缩算法在同一类型的数据文件上的效果进行了比较。

我们选择了文本文件进行分析。

图表1:文本文件的压缩率比较压缩算法效果比较压缩算法效果比较从图表1中可以看出,gzip算法在文本文件的压缩上表现最好,其次是tar算法,zip算法的效果相对较差。

4. 结论通过本次实验的数据分析,我们得出了以下结论: - 不同类型的数据文件在不同的压缩算法下的压缩率有所不同。

- 对于文本文件,gzip算法表现最好,zip算法效果相对较差。

压缩算法的选择应该根据具体的应用场景和需求来进行,综合考虑压缩率和解压缩速度等因素。

数据压缩实验报告(3篇)

数据压缩实验报告(3篇)

第1篇一、实验目的1. 了解数据压缩的基本原理和方法。

2. 掌握常用数据压缩算法的应用。

3. 分析不同数据压缩算法的性能和适用场景。

二、实验环境1. 操作系统:Windows 102. 编程语言:Python3. 数据压缩工具:Huffman编码、LZ77、LZ78、RLE、JPEG、PNG三、实验内容1. Huffman编码2. LZ77编码3. LZ78编码4. RLE编码5. 图像压缩:JPEG、PNG四、实验步骤1. Huffman编码(1)设计Huffman编码树,计算每个字符的频率。

(2)根据频率构建Huffman编码树,为每个字符分配编码。

(3)将原始数据按照Huffman编码进行编码,得到压缩数据。

(4)解压缩:根据编码表还原原始数据。

2. LZ77编码(1)设计LZ77编码算法,查找匹配的字符串。

(2)将原始数据按照LZ77编码进行编码,得到压缩数据。

(3)解压缩:根据编码表还原原始数据。

3. LZ78编码(1)设计LZ78编码算法,查找匹配的字符串。

(2)将原始数据按照LZ78编码进行编码,得到压缩数据。

(3)解压缩:根据编码表还原原始数据。

4. RLE编码(1)设计RLE编码算法,统计连续字符的个数。

(2)将原始数据按照RLE编码进行编码,得到压缩数据。

(3)解压缩:根据编码表还原原始数据。

5. 图像压缩:JPEG、PNG(1)使用JPEG和PNG工具对图像进行压缩。

(2)比较压缩前后图像的质量和大小。

五、实验结果与分析1. Huffman编码(1)压缩前后数据大小:原始数据大小为100KB,压缩后大小为25KB。

(2)压缩效率:压缩比约为4:1。

2. LZ77编码(1)压缩前后数据大小:原始数据大小为100KB,压缩后大小为35KB。

(2)压缩效率:压缩比约为3:1。

3. LZ78编码(1)压缩前后数据大小:原始数据大小为100KB,压缩后大小为30KB。

(2)压缩效率:压缩比约为3.3:1。

数据结构实验报告4文件压缩概要

数据结构实验报告4文件压缩概要

数据结构与程序设计实验实验报告哈尔滨工程大学实验报告四一、问题描述哈夫曼编码是一种常用的数据压缩技术,对数据文件进行哈夫曼编码可大大缩短文件的传输长度,提高信道利用率及传输效率。

要求采用哈夫曼编码原理,统计文本文件中字符出现的词频,以词频作为权值,对文件进行哈夫曼编码以达到压缩文件的目的,再用哈夫曼编码进行译码解压缩。

统计待压缩的文本文件中各字符的词频,以词频为权值建立哈夫曼树,并将该哈夫曼树保存到文件HufTree.dat 中。

根据哈夫曼树(保存在HufTree.dat 中)对每个字符进行哈夫曼编码,并将字符编码保存到HufCode.txt 文件中。

压缩:根据哈夫曼编码,将源文件进行编码得到压缩文件CodeFile.dat。

解压:将CodeFile.dat 文件利用哈夫曼树译码解压,恢复为源文件。

二、数据结构设计由于哈夫曼树中没有度为1的结点,则一棵树有n个叶子结点的哈夫曼树共有2n-1个结点,可以存储在一个大小为2n-1的一维数组中,而且对每个结点而言,即需知双亲结点的信息,又需知孩子结点的信息,由此可采用如下数据结构。

1.使用结构体数组统计词频,并存储:typedef struct Node{int weight; //叶子结点的权值char c; //叶子结点int num; //叶子结点的二进制码的长度}LeafNode[N];2.使用结构体数组存储哈夫曼树:typedef struct{unsigned int weight;//权值unsigned int parent, LChild, RChild;}HTNode,Huffman[M+1]; //huffman树3.使用字符指针数组存储哈夫曼编码表:typedef char *HuffmanCode[2*M]; //haffman编码表三、算法设计1.读取文件,获得字符串void read_file(char const *file_name, char *ch){FILE *in_file = Fopen(file_name, "r");unsigned int flag = fread(ch, sizeof(char), N, in_file);if(flag == 0){printf("%s读取失败\n", file_name);fflush(stdout);}printf("读入的字符串是: %s\n\n", ch);Fclose(in_file);int len = strlen(ch);。

文件管理实验报告结果(3篇)

文件管理实验报告结果(3篇)

第1篇一、实验目的本次实验旨在通过实际操作,验证文件管理的有效性和可行性,并对文件管理系统的性能进行评估。

通过实验,了解文件管理的相关原理和方法,提高文件管理的实践能力。

二、实验环境1. 操作系统:Windows 102. 文件管理系统:Windows文件管理器3. 实验数据:实验过程中产生的文件和数据三、实验内容1. 文件创建与删除2. 文件夹创建与删除3. 文件与文件夹的复制、移动、重命名4. 文件属性的设置与修改5. 文件搜索与查找6. 文件权限管理7. 文件压缩与解压四、实验步骤1. 文件创建与删除(1)在Windows文件管理器中,新建一个名为“实验文件.txt”的文本文件。

(2)在“实验文件.txt”上右击,选择“删除”,确认删除。

2. 文件夹创建与删除(1)在Windows文件管理器中,新建一个名为“实验文件夹”的文件夹。

(2)在“实验文件夹”上右击,选择“删除”,确认删除。

3. 文件与文件夹的复制、移动、重命名(1)将“实验文件.txt”复制到“实验文件夹”中。

(2)将“实验文件.txt”移动到桌面。

(3)将“实验文件.txt”重命名为“实验文件修改.txt”。

4. 文件属性的设置与修改(1)在“实验文件修改.txt”上右击,选择“属性”,设置文件属性为“只读”。

(2)修改“实验文件修改.txt”的属性为“隐藏”。

5. 文件搜索与查找(1)在Windows文件管理器中,输入“实验文件”进行搜索。

(2)使用“查找”功能,查找“实验文件修改.txt”。

6. 文件权限管理(1)在“实验文件夹”上右击,选择“属性”,点击“安全”标签。

(2)添加用户权限,设置权限为“完全控制”。

7. 文件压缩与解压(1)将“实验文件夹”压缩为“实验文件夹.zip”。

(2)解压“实验文件夹.zip”到指定位置。

五、实验结果与分析1. 文件创建与删除:实验成功创建和删除了文件,验证了文件管理的可行性。

2. 文件夹创建与删除:实验成功创建和删除了文件夹,验证了文件管理的可行性。

LZSS压缩算法实验报告

LZSS压缩算法实验报告

LZSS压缩算法实验报告一、引言LZSS是一种常用的压缩算法,被广泛应用于数据压缩领域。

它的核心思想是通过利用数据中存在的重复信息来实现压缩。

本实验主要对LZSS压缩算法进行研究与实验,评估其压缩效果和性能。

二、算法原理LZSS算法是一种基于滑动窗口和查找缓冲区的字典算法。

其主要思想是将输入数据分为两个部分:滑动窗口和查找缓冲区。

滑动窗口维护了最长匹配的前缀字符串,而查找缓冲区则用来寻找重复的字符串。

具体实现步骤如下:1.初始化滑动窗口和查找缓冲区;2.在滑动窗口中寻找与查找缓冲区中最长匹配的字符串;3.若找到匹配字符串,则将其标记为索引和长度的形式;4.若未找到匹配字符串,则将当前字符输出;5.更新滑动窗口和查找缓冲区;6.重复2-5步骤,直到所有字符处理完毕。

三、实验设计本实验的主要目的是评估LZSS压缩算法的压缩效果和性能表现。

为了完成实验,我们设计了以下实验流程:1.实现LZSS压缩和解压缩算法;2.准备不同类型和大小的文件,用于测试压缩算法的效果;3.运行压缩算法,并记录压缩比、压缩时间和解压缩时间;4.对比不同类型和大小的文件的压缩比和压缩时间;5.分析实验结果并给出评估。

四、实验结果与分析我们分别对文本文件、图像文件和音频文件进行了压缩实验。

实验结果如下:1.文本文件压缩实验结果:压缩比为70%,压缩时间为0.5秒,解压缩时间为0.3秒。

2.图像文件压缩实验结果:压缩比为80%,压缩时间为1秒,解压缩时间为0.6秒。

3.音频文件压缩实验结果:压缩比为60%,压缩时间为0.8秒,解压缩时间为0.4秒。

从实验结果可以看出,不同类型的文件对LZSS压缩算法的效果存在差异。

文本文件由于存在大量的重复信息,所以可以获得较高的压缩比。

而图像文件和音频文件的压缩比较低,因为它们的数据特征较为复杂,存在较少的重复信息。

压缩时间和解压缩时间较短,说明LZSS压缩算法具有较好的性能表现。

五、总结本实验通过对LZSS压缩算法的实验研究,评估了其压缩效果和性能表现。

文件压缩与解压缩实践

文件压缩与解压缩实践

文件压缩与解压缩实践摘要随着人们对数据的大量需求以及计算机使用时间的增加,计算机磁盘上的文件越来越大,越来越多。

如何让有限的磁盘空间容纳更多的数据成为需要解决的问题。

一方面,高速发展的存储技术以提高磁盘容量来解决这样的需求,但随着网络环境下数据传递的产生以及带宽的限制,大容量数据问题日益突出。

在这两种需求的推动下,对数据压缩的需求产生了。

人们可以将文件在不改变其本身的条件下,将其以更小的占用空间存储,并且在需要的时候将文件恢复成原有的样子,这就是压缩目的。

本论文主要研究文件的无损压缩技术,并简要介绍了文件压缩的分类、几种常用的无损压缩格式和常用的压缩算法。

运用LZ77字典算法、懒惰匹配算法和Huffman编码算法,使用Java语言在Jbuilder2006环境下设计了使用GZIP算法对文件压缩与解压缩的实现程序。

用户可以根据自己的需求,使用此程序方便地对文件进行压缩或者解压缩操作。

关键词:压缩;解压缩;GZIP;JavaPractice of File Compression and DecompressionAbstractAs the great demand for data and the using time of computer are increasing, computer files on the disk grow more and more. How to make the limited disk space to store more data has became a problem crying out for solutions. On one hand, the rapid development of storage technology that can increase the disk capacity, can meet such demand. However, with the emergence of data transmission in a network environment and the bandwidth limitations, the problem of large-capacity data is increasingly prominent. With the promotion of both demands, the need for data compression and decompression is generated. People can store a file with a smaller storage space without changing the file’s own condition, and can restore the file; that is the purpose of data compression and decompression. This treatise principally research file lossless compression, otherwise, briefly introduced classification of file compression, some general lossless compression format and general compression algorithm. A procedure within algorithm called GZIP were designed for file compression and decompression in Java language under the circumstances of Jbuilder2006,which used LZ77 dictionary algorithm, lazy match algorithm and Huffman coding algorithm. Users could use this procedure compress or decompress files expediently according to their demand.Key words: Compression; Decompression; GZIP; Java目录论文总页数:21页1 引言 (1)1.1课题背景 (1)1.2国内外现有的研究成果 (1)2 压缩与解压缩程序分析 (2)2.1需求分析 (2)2.2使用的算法理论 (2)2.2.1 LZ77算法简介 (2)2.2.2 Huffman算法简介 (3)2.2.3 GZIP算法原理分析 (4)2.3开发环境 (4)3 总体设计 (4)3.1程序功能模块 (5)3.2模块分析与流程图 (5)3.2.1 压缩模块 (5)3.2.2 解压缩模块 (6)3.3程序中各个类的初步定义 (7)4 详细设计和实现 (8)4.1 压缩的程序流程 (8)4.2 解压缩的程序流程 (9)4.3 主函数代码 (10)4.3.1 gzip压缩模块代码 (10)4.3.2 ungzip解压缩模块代码 (11)4.4 程序界面设计 (12)5 软件系统测试 (17)5.1 运行环境 (17)5.2 测试方法 (17)5.3 测试结果 (17)5.3.1 使用程序对txt文件压缩 (17)5.3.2 使用程序对bmp图象文件压缩 (18)5.3.3 使用程序对doc文件压缩 (18)结论 (19)参考文献 (19)致谢 (20)声明 (21)1引言1.1课题背景随着科学技术的进步,信息技术越来越广泛地应用到社会的各个行业和领域,互联网深刻地改变着人们的生活方式,推动着人类文明的进步。

用哈夫曼编码实现文件压缩实验报告【管理资料】

用哈夫曼编码实现文件压缩实验报告【管理资料】

《用哈夫曼编码实现文件压缩》实验报告课程名称数据结构B 实验学期 2013 至 2014 学年第一学期学生所在系部计算机学院年级 2013 专业班级学生姓名学号任课教师实验成绩一、实验题目:用哈夫曼编码实现文件压缩二、实验目的:1、了解文件的概念。

2、掌握线性链表的插入、删除等算法。

3、掌握Huffman树的概念及构造方法。

4、掌握二叉树的存储结构及遍历算法。

5、利用Huffman树及Huffman编码,掌握实现文件压缩的一般原理。

三、实验设备与环境:微型计算机、Windows 系列操作系统、Visual C++四、实验内容:根据输入小写英文字母和输入的对应权值创建哈夫曼树,可以求出每个小写英文字母的哈夫曼编码,将文本中的字母对应的哈夫曼编码写入文本中,实现对文本的编码。

五、概要设计:(1)构造Hufffman树的Hufffman算法构造Huffman树步骤:1.根据给定的n个权值{w1,w2,……wn},构造n棵只有根结点的二叉树,起权值为wj。

2.在森林中选取两棵根结点权值最小和次小的树作左右子树,构造一棵新的二叉树,置新二叉树根结点权值为其左右子树根结点权值之和。

3.在森林中删除这两棵树,同时将新得到的二叉树加入森林中。

重复上述两步,直到只含一棵树为止,这棵树即哈夫曼树。

算法结构如图:(2)Huffman编码:数据通信用的二进制编码思想:根据字符出现频率编码,使电文总长最短编码:根据字符出现频率构造Huffman树,然后将树中结点引向其左孩子的分支标“0”,引向其右孩子的分支标“1”;每个字符的编码即为从根到每个叶子的路径上得到的0、1序列。

(3) 文本编码读取存放在文本中的字母,一对一的进行编译,将对应的编码存放到另一个文本中。

#include<>#include<>#include<>//树结点定义typedef struct{int weight;int parent;int lchild;int rchild;}HTNode,*HuffmanTree;static char N[100];//用于保存字符//赫夫曼编码,char型二级指针typedef char **HuffmanCode;//封装最小权结点和次小权结点typedef struct{int s1;int s2;}MinCode;//函数声明void Error();HuffmanCode HuffmanCoding(HuffmanTree &HT,HuffmanCode HC,int *w,int n);MinCode Select(HuffmanTree HT,int n);//当输入1个结点时的错误提示void Error(){printf("一个字符不进行编码!\n");exit(1);}//构造赫夫曼HT,编码存放在HC中,w为权值,n为结点个数HuffmanCode HuffmanCoding(HuffmanTree &HT,HuffmanCode HC,int *w,int n){int i,s1=0,s2=0;HuffmanTree p;char *cd;int f,c,start,m;MinCode min;if(n<=1){Error();//只有一个结点不进行编码,直接exit(1)退出}m=2*n-1;//赫夫曼码需要开辟的结点大小为2n-1HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));//开辟赫夫曼树结点空间m+1//初始化n个叶子结点for(p=HT,i=0;i<=n;i++,p++,w++){p->weight=*w;p->parent=0;p->lchild=0;p->rchild=0;}//将n-1个非叶子结点的初始化for(;i<=m;i++,p++){p->weight=0;p->parent=0;p->lchild=0;p->rchild=0;}//构造赫夫曼树for(i=n+1;i<=m;i++){min=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;//赋权和}//打印赫夫曼树printf("HT List:\n");printf("Number\t\tweight\t\tparent\t\tlchild\t\trchild\n");for(i=1;i<=m;i++){printf("%d\t\t%d\t\t%d\t\t%d\t\t%d\t\n",i,HT[i].weight,HT[i].parent,HT[i].lchild,HT[i].rchild);}//从叶子结点到根节点求每个字符的赫夫曼编码HC=(HuffmanCode)malloc((n+1)*sizeof(char *));cd=(char *)malloc(n*sizeof(char *));//为赫夫曼编码动态分配空间cd[n-1]='\0';//编码结束符//求叶子结点的赫夫曼编码for(i=1;i<=n;i++){start=n-1;//定义左子树为0,右子树为1/*从最下面的1号节点开始往顶部编码(逆序存放),然后编码2号节点,3号......*/for(c=i,f=HT[i].parent; f!=0; c=f,f=HT[f].parent){if(HT[f].lchild==c)cd[--start]='0';elsecd[--start]='1';}//为第i个字符分配编码空间HC[i]=(char *)malloc((n-start)*sizeof(char *));//将当前求出结点的赫夫曼编码复制到HCstrcpy(HC[i],&cd[start]);}free(cd);return HC;}MinCode Select(HuffmanTree HT,int n){int min,secmin;int temp = 0;int i,s1,s2,tempi = 0;MinCode code ;s1=1;s2=1;min = 999999;//足够大//找出权值weight最小的结点,下标保存在s1中for(i=1;i<=n;i++){if(HT[i].weight<min && HT[i].parent==0){min=HT[i].weight;s1=i;}}secmin = 999999;//足够大//找出权值weight次小的结点,下标保存在s2中for(i=1;i<=n;i++){if((HT[i].weight<secmin) && (i!=s1) && HT[i].parent==0){secmin=HT[i].weight;s2=i;}}//放进封装中=s1;=s2;return code;}void Compression(HuffmanCode HC) //翻译原文档字符为赫夫曼编码FILE *fp1,*fp2;char ch;if((fp1 = fopen("","r")) == NULL)exit(0);if((fp2 = fopen("","a")) == NULL)exit(0);ch = fgetc(fp1);while((int)ch!= -1){switch(ch){case 'a': fputs(HC[1],fp2); break;case 'b': fputs(HC[2],fp2); break;case 'c': fputs(HC[3],fp2); break;case 'd': fputs(HC[4],fp2); break;case 'e': fputs(HC[5],fp2); break;case 'f': fputs(HC[6],fp2); break;case 'g': fputs(HC[7],fp2); break;case 'h': fputs(HC[8],fp2); break;case 'i': fputs(HC[9],fp2); break;case 'j': fputs(HC[10],fp2); break;case 'k': fputs(HC[11],fp2); break;case 'l': fputs(HC[12],fp2); break;case 'm': fputs(HC[13],fp2); break;case 'n': fputs(HC[14],fp2); break;case 'o': fputs(HC[15],fp2); break;case 'p': fputs(HC[16],fp2); break;case 'q': fputs(HC[17],fp2); break;case 'r': fputs(HC[18],fp2); break;case 's': fputs(HC[19],fp2); break;case 't': fputs(HC[20],fp2); break;case 'u': fputs(HC[21],fp2); break;case 'v': fputs(HC[22],fp2); break;case 'w': fputs(HC[23],fp2); break;case 'x': fputs(HC[24],fp2); break;case 'y': fputs(HC[25],fp2); break;case 'z': fputs(HC[26],fp2); break;default: printf(" 没有编码!\n");}ch = fgetc(fp1);}fclose(fp1);fclose(fp2);void main(){HuffmanTree HT=NULL;HuffmanCode HC=NULL;int *w=NULL;int i,n;printf("输入字符:");gets(N);n = strlen(N);w=(int *)malloc((n+1)*sizeof(int *));//开辟n+1个长度的int指针空间w[0]=0;printf("输入结点权值:\n");//输入结点权值for(i=1;i<=n;i++){printf("w[%d]=",i);scanf("%d",&w[i]);}//构造赫夫曼树HT,编码存放在HC中,w为权值,n为结点个数HC=HuffmanCoding(HT,HC,w,n);//输出赫夫曼编码printf("赫夫曼:\n");printf("Number\t\tWeight\t\tCode\n");for(i=1;i<=n;i++){printf("%c\t\t%d\t\t%s\n",N[i-1],w[i],HC[i]);}Compression(HC);}选取权值最小的结点的算法:选取权值次小的结点的算法:哈夫曼树建立的算法:哈夫曼编码的算法:七、测试结果及分析:4.输出哈夫曼树:5.字符对应编码:6.要编码的文本:7.编译后的文本:价。

基于哈夫曼编码实现文本文件的压缩和解压缩实验报告模板

基于哈夫曼编码实现文本文件的压缩和解压缩实验报告模板

本科学生设计性实验报告软件工程技能实践Ⅰ项目组长陈启学号_*******专业软件工程班级_15软件7 班成员陈启杨林昌邓志远万胜实验项目名称_指导教师及职称__讲师__开课学期2015 至2016 学年第二学期一、实验设计方案1、实验任务与目的(简单介绍实验内容,说明实验任务和目的)1.1实验内容根据ascii码文件中各ascii字符出现的频率情况创建Haffman树,再将各字符对应的哈夫曼编码写入文件中,实现文件压缩。

对于给定的一组字符,可以根据其权值进行哈夫曼编码,并能输出对应的哈夫曼树和哈夫曼编码;实现哈夫曼解码。

能够分析文件,统计文件中出现的字符,再对文件进行编码,实现文件的压缩和解压缩,能够对于文件的压缩,比例进行统计,能够打印文件。

分析与设计哈夫曼树的存储结构,实现哈夫曼算法以及编码与译码基本功能,并对任意文本文件利用哈夫曼编码进行压缩得到压缩文件,然后进行解压缩得到解压文件。

1.2实验任务和目的1.2.1了解文件的概念。

1.2.2掌握线性链表的插入、删除等算法。

1.3.3掌握Huffman树的概念及构造方法。

1.4.4掌握二叉树的存储结构及遍历算法。

1.5.5利用Huffman树及Huffman编码,掌握实现文件压缩的一般原理。

2、实验思路(详细描述解决问题的整体思路、涉及的算法思想及数据结构等)2.1整体思路2.2涉及的算法思想及数据结构:2.2.1输入要压缩的文件首先运行的时候,用户主界面上有菜单提示该如何使用软件,根据菜单提示选择所要执行的项,依次进行,因为各个环节之间有先后顺序。

第一步为输入压缩软件的名称,由键盘输入文件路径和文件名称,读入字符数组中,打开该文件,按照提示进行压缩。

若打不开,则继续输入。

2.2.2读文件并计算字符频率文件将信息存放在字符数组中;计算每个字符出现的次数,申请一个结构体数组空间,用读取的字符减去字符结束符作为下标记录字符的频率。

2.2.3根据字符的频率,利用Huffman编码思想创建Huffman树将所记录的字符的频率作为权值来创建Huffman树,依次选择权值最小的两个字符作为左右孩子,其和作为父结点的权值,依次进行下去,直到所有的字符结点都成为叶子结点。

文件和文件夹上机报告(压缩和解压缩)

文件和文件夹上机报告(压缩和解压缩)
实践操作
1、安装WinRAR文件到D分区“系统工具”文件夹下。
2、在“E”分区下建立“班”文件夹,在“班”文件夹下以自己的姓名建立一个文件夹。
3、将接收的作业,剪切到以自己姓名命名的文件夹下。
4、复制“班”文件夹到“F”分区下,并打开,然后将以自己姓名命名的文件夹重命名为“作业备份”。
5、返回到”E”分区,自己的姓名的文件夹下,选择所有word文档,“添加到压缩文件----”仔细观察对话框,分别以“存储”和“最好”两种压缩方式,压缩成“文档1”和“文档2”两个压缩文件。
《Windows7内容
《Windows7》快速入门------------使用Windows7中压缩和解压缩文件与文件夹
课前自学
1、压缩文件名的扩展名是。
2、“压缩方式”下拉列表框中的选项的意义是:
“最好”表示;
“存储”表示;
自主探究
1、文件压缩的意义:
2、设置压缩文件密码的操作步骤:
每组小组长检查你的组员上机操作情况。
6、分别查看两个压缩文件的属性,有什么区别?
7、从发送的作业中,选取“Exel资料”压缩文件,解压到以自己姓名命名的文件夹下。并将“Exel资料”压缩文件备份到“作业备份”中。
8、选取“Exel资料”压缩文件,按右键,在右键菜单中,分别用四种解压方式解压文件。并说明每种解压方式的异同。
9、找到“作业备份”文件夹,并将此文件夹下的所有文件压缩,并设置密码。

云存储系统数据压缩与解压实验报告

云存储系统数据压缩与解压实验报告

云存储系统数据压缩与解压实验报告云存储系统是当今信息技术领域中备受关注的热门话题之一。

随着大数据时代的来临,云存储系统的数据压缩与解压技术也日益受到关注。

本实验旨在通过对云存储系统中数据压缩与解压的实践操作,探讨其在实际应用中的有效性和效果。

1. 实验目的本实验的目的是通过对云存储系统中数据压缩与解压的实践操作,深入了解云存储系统的数据压缩与解压技术,并评估其在实际应用中的效果。

2. 实验原理数据压缩是云存储系统中常用的一种技术,通过对数据进行压缩,可以减小数据的存储空间,并加快数据的传输速度。

常见的数据压缩算法包括哈夫曼编码、LZW 编码等。

在本实验中,我们选取了哈夫曼编码算法作为示例,通过对给定的数据进行压缩和解压操作,验证该算法的有效性。

3. 实验步骤3.1 数据压缩在云存储系统中,选择一批待压缩的数据作为实验对象。

通过调用哈夫曼编码算法对这些数据进行压缩,并记录压缩所需时间以及压缩比例。

3.2 数据解压在完成数据压缩后,选取其中一部分压缩后的数据进行解压操作,通过调用哈夫曼编码算法进行解压,并记录解压所需时间。

4. 实验结果与分析4.1 数据压缩结果在对待压缩的数据进行处理后,我们得到了压缩后的数据以及对应的压缩比例。

例如,对于100MB的待压缩数据,通过哈夫曼编码算法进行压缩后,我们得到了50MB的压缩数据,压缩比为50%。

4.2 数据解压结果通过对压缩后的数据进行解压操作,我们得到了与原始数据完全一致的解压结果。

这表明所选用的哈夫曼编码算法能够有效地将压缩数据恢复为原始数据。

4.3 性能评估哈夫曼编码算法在云存储系统中的数据压缩与解压操作中,具有较低的时间复杂度和较高的压缩比例。

根据实验结果统计,我们可以得出以下结论:- 压缩时间:在数据量较大的情况下,哈夫曼编码算法的压缩时间较长。

因此,在实际应用中,需要根据实际情况综合考虑压缩时间和压缩比例来选择相应的压缩算法。

- 解压时间:通过哈夫曼编码算法进行解压操作所需时间相对较短,可以在较短的时间内实现数据的解压缩,提高系统的响应速度。

压缩解压缩实验报告

压缩解压缩实验报告

实验报告班级0901101 学号PB09210173 姓名饶亚民日期2010-11-10 一、题目要求:利用Huffman树及其编码原理写一个压缩和解压缩程序二、概要设计根据对用户输入的内容判断用户是要求压缩还是解压缩,若是压缩,则读入需压缩的文件(以二进制形式打开),求文件中字符的权重,构建Huffman树,求每个字符的Huffman编码,然后依次读入需压缩文件的内容,把其每个字符用其Huffman编码代换存入一数组中,输出到输出文件中。

输出文件格式为--.zap(也是二进制形式输出)。

若是解压缩,则根据读入文件的内容(以二进制形式打开),先判断是否为本压缩程序所压缩,若非,则报错。

若是,则依次读入存入该文件中的原来压缩文件的后缀名,原来文件中每个字符的权重,然后依据已存的每个字符的权重构建Huffman树,接着求每个字符的Huffman编码。

然后依次读入文件中的已存的以Huffman编码结果储存的0和1字符,按照Huffman编码结果,左子树为0,右子树为1,直至叶子节点,然后就可得到该Huffman编码所存储的字符值,然后依次输出到输出文件中,其中有一个count,用来记录已输出的字符个数,当它等于被压缩的文件长度时就停止。

三、详细设计详细数据结构定义:#include<stdio.h>#include<stdlib.h>#include<malloc.h>#include<string.h>#include"head.cpp"#include"BitWriting-Reading.cpp"#include"Directions.cpp"#include"Compress.cpp"#include"FindName.cpp"#include"filecompress.cpp"#include"Huffman Code.cpp"#include"DeCompress.cpp"#include"Match.cpp"#define TRUE 1#define FALSE 0#define ERROR 0#define OK 1typedef int Status;typedef struct{unsigned int weight;unsigned int parent,lchild,rchild;}HTNode,*HuffmanTree;typedef char **HuffmanCode;具体实现过程:main(int argc,char *argv[])//若argc=1则按报错处理然后调用Match函数Match(argv[1],flag),其作用是用来判断用户输入的内容Status Match(char *argv,int &flag){char *parameters[]={"compress","decompress","help"};int i;for(i=0;i<3;++i){if(!strcmp(parameters[i],argv)){flag=i+1;return OK;}}flag=0;return OK;}若flag=0,则按报错处理,并提示用户可以参考’help’;若flag=1,则说明是要压缩,接着判断argv[2]是否为空,若不为空,则将其视为输出文件的文件名,若为空,则默认为输入文件名为输出文件名,仅后缀不同而已。

哈夫曼文件压缩实验报告

哈夫曼文件压缩实验报告

哈夫曼文件压缩实验报告摘要:哈夫曼编码是一种常用的文件压缩算法,在本实验中我们通过使用哈夫曼编码算法对文件进行压缩和解压缩,来评估该算法在文件压缩方面的效果。

通过实验结果分析,我们发现哈夫曼编码能够有效地减小文件的大小,同时保持压缩后文件的可还原性。

1. 引言文件压缩是计算机科学领域的一个重要研究方向,它能够有效地减小文件的大小,节省存储空间和传输带宽。

哈夫曼编码作为一种经典的文件压缩算法,已被广泛应用于实际的文件压缩和传输中。

本实验旨在通过对哈夫曼编码的实际应用进行实验,评估其在文件压缩方面的效果。

2. 实验设计本实验分为三个步骤:文件读取、哈夫曼编码和压缩、解压和文件写入。

首先,我们需要从硬盘上读取待压缩的文件,并将其转化为二进制数据流。

接下来,我们使用哈夫曼编码算法对二进制数据流进行编码,生成编码后的数据流。

最后,我们根据编码表对编码后的数据流进行解码,恢复原始的二进制数据流,并将其写入硬盘上。

3. 实验过程首先,我们通过在计算机上选择一个待压缩的文件作为实验对象,然后设计一个程序来读取该文件的内容,并将其转化为二进制数据流。

为了保证实验结果的准确性,我们选择了不同类型和不同大小的文件进行实验,包括文本文件、图像文件和音频文件等。

接下来,我们使用哈夫曼编码算法对二进制数据流进行编码。

哈夫曼编码算法的核心思想是:将出现频率较高的字符用较短的编码表示,而将出现频率较低的字符用较长的编码表示,以达到最小化编码长度的效果。

在编码过程中,我们需要构建哈夫曼树和哈夫曼编码表。

哈夫曼树通过合并出现频率最低的两个节点来构建,最终生成一棵以根节点为基础的哈夫曼树。

哈夫曼编码表则是根据哈夫曼树的结构和编码规则生成的,将每个字符与对应的编码一一对应。

压缩实验实验报告2024

压缩实验实验报告2024

篇章一:引言概述在物理学实验中,压缩实验是一种常见的实验方法,用于研究物体在受压力作用下的力学性质。

本实验旨在通过对物体的压缩过程进行观察和分析,从而深入理解压缩力学的基本原理。

通过实验结果的观察和分析,可以得出一定的结论,并为相关领域的研究提供参考。

篇章二:实验前准备2.1 实验材料和装置准备本次实验需要准备的材料和装置包括:压缩实验装置、弹簧、负荷、示波器、电源等。

实验装置应该经过检查,以确保其正常工作,并根据需求调整合适的实验参数。

2.2 实验目标和预期结果本实验的主要目标是研究物体在受到压力作用下的压缩力学性质。

预期结果包括:能够观察到物体的压缩过程,并测量压缩力、弹性系数等物理量,从而得出相关结论。

篇章三:实验过程和数据处理3.1 实验步骤3.1.1 设置实验装置首先,将压缩实验装置放置在实验台上,并将所需的材料和装置连接起来。

调整装置,使之处于合适的工作状态。

3.1.2 加载负荷根据实验要求,加装合适的负荷,并记录下负荷的数值。

注意,负荷的加装过程应该缓慢进行,以避免对实验装置和样品造成损坏。

3.1.3 观察和记录压缩过程通过示波器观察物体压缩的过程,并记录下关键的数据,比如实验开始时的长度、实验进行中的长度等。

3.2 数据处理和分析3.2.1 绘制压缩曲线根据实验记录的数据,绘制出物体的压缩曲线。

对于每个负荷值,记录下相应的压缩量,并绘制出与压缩量的关系曲线。

3.2.2 计算弹性系数通过压缩曲线的斜率计算物体的弹性系数。

根据一定的公式和数据分析方法,得出相应的结果,并进行数据修正和误差分析。

篇章四:实验结果与讨论4.1 压缩实验观察结果根据实验记录的数据和观察,对不同负荷值下物体的压缩过程进行详细的描述。

结合压缩曲线和弹性系数的计算结果,对实验结果进行分析。

4.2 弹性模量的计算和分析根据实验结果,计算物体的弹性模量。

通过与理论值的比较,评估实验结果的准确性和可靠性。

4.3 数据修正和误差分析根据实验过程中可能存在的误差来源,对实验数据进行修正。

压缩实验报告

压缩实验报告

压缩实验报告压缩实验报告引言:压缩技术是现代信息技术中不可或缺的一部分。

它可以将大量的数据压缩成较小的体积,从而节省存储空间和传输带宽。

本实验旨在探究不同压缩算法的效果,并比较它们的优缺点。

一、实验设备和方法本实验使用了一台配置较高的计算机,并安装了常用的压缩软件。

实验过程中,我们选择了两种常见的压缩算法:Huffman编码和Lempel-Ziv-Welch(LZW)算法。

二、实验过程1. Huffman编码:Huffman编码是一种基于字符出现频率的压缩算法。

它通过构建哈夫曼树,将出现频率较高的字符用较短的编码表示,而出现频率较低的字符用较长的编码表示。

我们首先选择了一个文本文件进行压缩实验。

通过对文件进行统计分析,我们得到了每个字符的出现频率。

然后,根据频率构建了一棵哈夫曼树,并生成了对应的编码表。

最后,我们将原始文本文件使用Huffman编码进行压缩,并记录了压缩后的文件大小。

2. LZW算法:LZW算法是一种基于字典的压缩算法。

它通过建立字典并将输入文本与字典中的条目进行匹配,从而实现压缩。

当输入文本中的字符序列在字典中不存在时,将其添加到字典中,并输出前一个匹配的条目的编码。

我们选择了一段音频文件进行LZW算法的压缩实验。

首先,我们将音频文件转化为二进制数据,并建立一个初始字典,包含所有可能的字符。

然后,按照LZW算法的步骤,将输入文本与字典中的条目进行匹配,并输出对应的编码。

最后,我们记录了压缩后的文件大小。

三、实验结果与分析通过对压缩后的文件大小进行比较,我们得出了以下结论:1. Huffman编码相对于LZW算法,在处理文本文件时具有更好的压缩效果。

这是因为文本文件中存在大量重复的字符,而Huffman编码可以根据字符的出现频率进行编码,从而实现较高的压缩比。

2. LZW算法在处理音频文件时表现更好。

音频文件中的数据通常具有较高的连续性,而LZW算法可以通过建立字典并匹配连续的字符序列,实现较好的压缩效果。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

院系:计算机学院实验课程:实验3实验项目:文本压缩与解压指导老师:开课时间:2010 ~ 2011年度第 1学期专业:班级:学生:学号:一、需求分析1.本程序能够实现将一段由大写字母组成的容转为哈弗曼编码的编码功能以及将哈弗曼编码翻译为字符的译码功能。

2.友好的图形用户界面,直观明了,每一个操作都有相应的提示,用户只需按着提示去做,便能轻松实现编码以及译码的效果,编码及译码结果都被保存成txt 文档格式,方便用户查看。

3.本程序拥有极大的提升空间,虽然现在只能实现对大写字母的译码以及编码,但通过改进鉴别的算法,即能够实现小写字母乃至其他特殊符号等的编码。

4.本程序可用于加密、解密,压缩后文本的大小将被减小,更方便传输5.程序的执行命令包括:1)初始化 2)编码 3)译码 4)印代码文件 5)印哈弗曼树 6)退出6.测试数据(1)THIS PROGRAM IS MY FAVOURITE(2)THIS IS MY FAVOURITE PROGRAMBUT THE REPORT IS NOT二、概要设计为实现上述功能,应有哈弗曼结点,故需要一个抽象数据类型。

1.哈弗曼结点抽象数据类型定义为:ADT HaffTree{数据对象:HaffNode* ht,HaffCode* hc基本操作:Haffman(int w[],int n)操作结果:构造哈弗曼树及哈弗曼编码,字符集权值存在数组w,大小为nsetdep()setdep(int p,int l)操作结果:利用递归,p为哈弗曼节点序号,l为哈弗曼节点深度setloc()操作结果:设置哈弗曼节点坐标,用以输出到界面setloc2()操作结果:设置哈弗曼节点坐标,用以输出到文本,默认状态下不启用} ADT HaffTree2.本程序包含4个模块1)主程序模块:接受用户要求,分别选择执行①初始化②编码③译码④印代码文件⑤印哈弗曼树⑥退出2)哈弗曼树单元模块——建立哈弗曼树3)哈弗曼编码单元模块——进行哈弗曼编码、译码4)响应用户操作,输出容到界面或文本各模块之间的关系如下:三、详细设计1.全局变量、结点int m_gcharnum;//记录字符集大小全局变量int t;//用于输入框弹出次数的计数int *w;//用于存储各个字符权值的数组int x;//用于计算各个哈弗曼结点x坐标的全局变量int initswitch;//用于判断是否已经进行了初始化操作int printtree;//用于判断哈弗曼树是否已经生成的操作HaffTree HF;//哈弗曼树类struct HaffNode{int weight;//记录结点权值int parent;//记录结点双亲序号int lchild;//记录结点左孩子序号int rchild;//记录结点右孩子序号int x;//记录x坐标int y;//记录y坐标int dep;//记录深度int sn;//记录空格个数int k;//0为左孩子,1为右孩子,-1为根string s;};struct HaffCode{int bit[28];//记录各结点的哈弗曼编码int start;//记录遍历哈弗曼树的起始位置int weight;//记录结点权值};2.哈弗曼树的实现//函数名:Haffman//功能:生成哈弗曼树,为每一个哈弗曼结点生成哈弗曼编码//函数参数:int w[]引入各个字符的权值// int n字符集大小void HaffTree::Haffman(int w[],int n){int i,j,m1,m2,x1,x2;//m1,m2表示最小、次小x1,x2表示左右孩子for(i=0;i<2*n-1;i++)//进行初始化操作,记录权值{if(i<n)ht[i].weight=w[i];else ht[i].weight=0;//赋权值ht[i].parent=0;//清空父母序号ht[i].lchild=-1;//清空左孩子序号ht[i].rchild=-1;//清空右孩子序号}for(i=0;i<n-1;i++)//寻找最小、次小,生成双亲{m1=m2=1000;x1=x2=0;for(j=0;j<n+i;j++){if(ht[j].weight<m1&&ht[j].parent==0)//如果权值比最小的小,且未获得双亲(未被访问),将其设为最小{m2=m1;x2=x1;m1=ht[j].weight;x1=j;}else if(ht[j].weight<m2&&ht[j].parent==0)//如果权值比次小的小,将其设为次小{m2=ht[j].weight;x2=j;}}ht[x1].parent=n+i;ht[x2].parent=n+i;ht[n+i].weight=ht[x1].weight+ht[x2].weight;ht[n+i].lchild=x1;ht[ht[n+i].lchild].k=0;//为左孩子添加标记ht[n+i].rchild=x2;ht[ht[n+i].rchild].k=1;//为右孩子添加标记}HaffCode cd;int child,parent;for(i=0;i<n;i++){cd.start=n-1;cd.weight=ht[i].weight;child=i;parent=ht[child].parent;while(parent!=0)//为每个结点设置哈弗曼编码值,左孩子为0,右孩子为1{if(ht[parent].lchild==child)cd.bit[cd.start]=0;elsecd.bit[cd.start]=1;cd.start--;child=parent;parent=ht[child].parent;}for(j=cd.start+1;j<n;j++){ hc[i].bit[j]=cd.bit[j];}//为每个结点生成哈弗曼编码hc[i].start=cd.start;hc[i].weight=cd.weight;}}3.主函数和其他函数的实现1)哈弗曼树类的成员函数的实现:///////////////////////////////////////////////////////////////////// //////函数名:setdep//功能:利用递归,为哈弗曼树各个结点记录深度//函数参数:无void HaffTree::setdep(){int i=2*m_gcharnum-2;setdep(i,1);}//函数名:setdep//功能:利用递归,为哈弗曼树各个结点记录深度//函数参数:int p引入哈弗曼结点序号// int l记录深度void HaffTree::setdep(int p,int l){if(p!=-1){setdep(ht[p].lchild,l+1);ht[p].dep=l;setdep(ht[p].rchild,l+1);}}///////////////////////////////////////////////////////////////////// //////函数名:setloc//功能:为各个哈弗曼结点确定坐标,以输出到界面//函数参数:无void HaffTree::setloc(){setdep();int f=1;if(initswitch==1){stack<int> s;int k;int i=2*m_gcharnum-2;while(!s.empty()||i!=-1)//如果栈不为空且序号不为-1{while(i!=-1){s.push(i);//入栈i=ht[i].lchild;//获取左孩子的序号}if(!s.empty()){k=s.top();//出栈s.pop();if(k!=-1){ht[k].x=x+f*10;ht[k].y=ht[k].dep*30;}i=ht[k].rchild;//获取右孩子的序号}f++;}}}///////////////////////////////////////////////////////////////////// //////函数名:setloc2,利用层次遍历思想实现//功能:为各个哈弗曼结点确定坐标,以输出到文档//函数参数:无void HaffTree::setloc2(){if(initswitch==1){queue<int> q;int k=2*m_gcharnum-2;ht[k].sn=1024;//设置第一个结点的空格值为1024个ht[k].k=-1;//标记第一个结点为根结点int d0=11;int d=1;int p;if(k!=-1){q.push(k);//入队}while(!q.empty()){while(d<=d0){if(!q.empty()){ p=q.front();}//出队else{ d++;break;}if(d==ht[p].dep)//如果d不等于当前深度,先不出队{if(d!=1){if(ht[p].k==0)//计算左孩子空格个数{ht[p].sn=ht[ht[p].parent].sn-1024/pow(2,ht[p].dep-1);}if(ht[p].k==1)//计算右孩子空格个数{ht[p].sn=ht[ht[p].parent].sn+1024/pow(2,ht[p].dep-1);}q.pop();}else{ q.pop();}if(ht[p].lchild!=-1){ q.push(ht[p].lchild);}//左孩子入队if(ht[p].rchild!=-1){ q.push(ht[p].rchild);}//右孩子入队}else{ d++;}}}}}2)程序主界面某些函数的实现:///////////////////////////////////////////////////////////////////// //////函数名:CP3View::OnDraw()//功能:画图//函数参数:CDC* pDCvoid CP3View::OnDraw(CDC* pDC){CP3Doc* pDoc = GetDocument();ASSERT_VALID(pDoc);// TODO: add draw code for native data hereCRect rect;GetClientRect(rect);///取得客户区域pDC-> FillRect(rect,&m_brushBackground); ///用背景画刷填充区域OnEraseBkgnd(pDC);CPen penblack;//定义画笔CBrush brush1;//定义画刷COLORREF oldbackcolor=RGB(255,255,255);//获取背景颜色penblack.CreatePen(PS_SOLID,2,RGB(255,0,0));//为画笔设定大小和颜色pDC->SelectObject(&penblack);brush1.CreateSolidBrush(oldbackcolor);//为画刷设定颜色pDC->SelectObject(&brush1);if(printtree==1)//如果显示树的按钮已被按下,则执行下面的容{HF.setloc();//设置各个节点坐标//利用非递归中序遍历思想画图stack<int> s;建栈int k;int i=2*m_gcharnum-2;while(!s.empty()||i!=-1){while(i!=-1){s.push(i);//入栈i=HF.ht[i].lchild;//获取左孩子序号}if(!s.empty()){k=s.top();//出栈s.pop();if(k!=-1){CString str(HF.ht[k].s.data());//获取当前哈弗曼结点的数据pDC->TextOut(HF.ht[k].x,HF.ht[k].y,str);//输出str的值}i=HF.ht[k].rchild;//获取右孩子序号//////////////////////////////////////////////////画线用if(HF.ht[k].lchild!=-1){pDC->MoveTo(HF.ht[k].x+4,HF.ht[k].y);pDC->LineTo(HF.ht[HF.ht[k].lchild].x+4,HF.ht[HF.ht[k].lchild].y);}if(HF.ht[k].rchild!=-1){pDC->MoveTo(HF.ht[k].x+4,HF.ht[k].y);pDC->LineTo(HF.ht[HF.ht[k].rchild].x+4,HF.ht[HF.ht[k].rchild].y);}////////////////////////////////////////////////// }}}}///////////////////////////////////////////////////////////////////// //函数名:CP3View::OnHandinput//功能:执行手动输入操作//函数参数:CDC* pDCvoid CP3View::OnHandinput(){// TODO: Add your command handler code hereifstream fip("HaffmanTree.txt");//利用文件流打开文件int i;if(!fip)//判断文件HaffmanTree.txt是否已经存在,若存在,则自动读取,若不存在,则手动输入{fip.close();fstream fop("HaffmanTree.txt",ios::out);//以写方式打开文件DINIT dint;//打开输入字符集大小对话框dint.DoModal();if(m_gcharnum!=0){t=0;DBLANKW dblankw;//打开输入空格权值对话框dblankw.DoModal();t++;for(t=1;t<m_gcharnum;t++){DCHARW dcharw;//打开输入字符及其权值对话框dcharw.DoModal();}}HF.Haffman(w,m_gcharnum);//生成哈弗曼树及代码fop<<m_gcharnum<<endl;for(i=0;i<m_gcharnum;i++){fop<<HF.ht[i].s<<endl;//写入字符fop<<HF.ht[i].weight<<endl;//写入字符所对应的权值fop<<HF.ht[i].parent<<endl;//写入双亲序号fop<<HF.ht[i].lchild<<endl;//写入左孩子序号fop<<HF.ht[i].rchild<<endl;//写入右孩子序号}fop.close();//关闭文件}else{AfxMessageBox("哈弗曼树文件已经存在,不需要手动输入,现执行自动读取!");fip.close();ifstream fip("HaffmanTree.txt");//以读文件方式打开文件fip>>m_gcharnum;//读取字符集大小char c[4];HF.ht=new HaffNode[2*m_gcharnum-1];HF.hc=new HaffCode[m_gcharnum];w=new int[m_gcharnum];for(i=0;i<m_gcharnum;i++){if(i==0){HF.ht[i].s=" ";}else{fip>>c;HF.ht[i].s=c;}fip>>w[i];//读取字符权值赋给w数组fip>>HF.ht[i].parent;//读取双亲序号fip>>HF.ht[i].lchild;//读取左孩子序号fip>>HF.ht[i].rchild;//读取右孩子序号}HF.Haffman(w,m_gcharnum);//生成哈弗曼树fip.close();//关闭文件}AfxMessageBox("初始化成功!");initswitch=1;}///////////////////////////////////////////////////////////////////// //函数名:CP3View::OnEncodinghinput//功能:执行编译手动输入操作//函数参数:CDC* pDCvoid CP3View::OnEncodinghinput(){// TODO: Add your command handler code hereif(initswitch==1)//判断是否已经初始化{DTOBETRAIN dtbt;//打开手动输入对话框dtbt.DoModal();}else{AfxMessageBox("您尚未执行初始化操作!请先执行初始化操作!");}}///////////////////////////////////////////////////////////////////// //函数名:CP3View::OnEncodingainput//功能:执行自动编码//函数参数:CDC* pDCvoid CP3View::OnEncodingainput(){// TODO: Add your command handler code hereif(initswitch==1)//判断是否已经初始化{CString m_path1,m_path2;//m_path1记录需要编码文件的路径,m_path2记录编码完成后文件的保存路径string cmp;char temp;AfxMessageBox("请选择要编码的文件的位置!");CFileDialog hFileDlg(true,NULL,NULL,OFN_FILEMUSTEXIST | OFN_READONLY | OFN_PATHMUSTEXIST,TEXT("文档文本 (*.txt)|*.txt|所有文件(*.*)|*.*|"),NULL);if(hFileDlg.DoModal() == IDOK){m_path1 = hFileDlg.GetPathName();//获取编码文件路径UpdateData(FALSE);}ifstream ldf(m_path1,ios::in);//以读方式打开文件AfxMessageBox("请选择代码文件的保存位置!");CFileDialog hFileDlg1(false,NULL,NULL,OFN_FILEMUSTEXIST | OFN_READONLY | OFN_PATHMUSTEXIST,TEXT("文档文本 (*.txt)|*.txt|所有文件(*.*)|*.*|"),NULL);if(hFileDlg1.DoModal() == IDOK){m_path2 = hFileDlg1.GetPathName();UpdateData(FALSE);}ofstream sff(m_path2);//以写方式打开文件while((temp=ldf.get())!=EOF){cmp=temp;int i=0,j=0;if(temp=='\n')//判断是否为回车{ sff<<'\n';}else{if(temp==0x20)//判断是否为空格{i=0;}else{while(cmp!=HF.ht[i].s)i++;}for(j=HF.hc[i].start+1;j<m_gcharnum;j++)sff<<HF.hc[i].bit[j];//比较字符,寻找对应的字符并将字符对应的哈弗曼编码写入结点}}AfxMessageBox("代码文件已保存成功!");}else{AfxMessageBox("您尚未执行初始化操作!请先执行初始化操作!");}}///////////////////////////////////////////////////////////////////// //函数名:CP3View::OnDecoding//功能:执行译码操作//函数参数:CDC* pDCvoid CP3View::OnDecoding(){// TODO: Add your command handler code hereif(initswitch==1)//判断是否已经初始化{CString m_path1,m_path2;//m_path1记录需要译码的文件的路径,m_path2记录译码后保存的文件的路径AfxMessageBox("请选择你需要译码的文件!");CFileDialog hFileDlg(true,NULL,NULL,OFN_FILEMUSTEXIST | OFN_READONLY | OFN_PATHMUSTEXIST,TEXT("文档文本 (*.txt)|*.txt|所有文件(*.*)|*.*|"),NULL);if(hFileDlg.DoModal() == IDOK){m_path1 = hFileDlg.GetPathName();UpdateData(FALSE);}AfxMessageBox("译码成功,请保存!");CFileDialog hFileDlg1(false,NULL,NULL,OFN_FILEMUSTEXIST | OFN_READONLY | OFN_PATHMUSTEXIST,TEXT("文档文本 (*.txt)|*.txt|所有文件(*.*)|*.*|"),NULL);if(hFileDlg1.DoModal() == IDOK){m_path2 = hFileDlg1.GetPathName();UpdateData(FALSE);}ifstream ldf(m_path1);//以读方式打开文件ofstream saf(m_path2);//以写方式打开文件char c;int i=2*m_gcharnum-2;while((c=ldf.get())!=EOF){if(c=='\n')//如果字符为回车,输出回车{saf<<endl;}else{if(c=='1')//如果字符为1,获取右孩子序号,走向右孩子{i=HF.ht[i].rchild;}if(c=='0')//如果字符值为0,获取左孩子序号走向左孩子{i=HF.ht[i].lchild;}if(HF.ht[i].lchild==-1&&HF.ht[i].rchild==-1)//如果当前结点没有左孩子也没有右孩子,则输出当前结点所存储的字符{if(i==0){saf<<" ";i=2*m_gcharnum-2;}else{saf<<HF.ht[i].s;i=2*m_gcharnum-2;}}}}ldf.close();saf.close();}else{AfxMessageBox("您尚未执行初始化操作!请先执行初始化操作!");}}///////////////////////////////////////////////////////////////////// //函数名:CP3View::OnSavhafftree//功能:保存哈弗曼树//函数参数:CDC* pDCvoid CP3View::OnSavhafftree(){// TODO: Add your command handler code hereCString m_path;//记录保存哈弗曼树文件的路径CFileDialog hFileDlg(false,NULL,NULL,OFN_FILEMUSTEXIST | OFN_READONLY | OFN_PATHMUSTEXIST,TEXT("文档文本 (*.txt)|*.txt|所有文件(*.*)|*.*|"),NULL);if(hFileDlg.DoModal() == IDOK){m_path = hFileDlg.GetPathName();UpdateData(FALSE);}ofstream saf(m_path);/*HF.setloc2();//该段容为输出哈弗曼树到文件的第二种方法,可输出树形,但由于太过占据空间,文档存储时不得不换行,导致树形扭曲,故舍弃此法queue<int> q;int p;int i=0;int d=1;int t1=0,t2=0;int d0=11;int k=2*m_gcharnum-2;if(k!=-1){q.push(k);}while(!q.empty()){while(d<=d0){if(!q.empty()){ p=q.front();t2=HF.ht[p].sn;}else{ d++;break;}if(d==HF.ht[p].dep){for(t1;t1<t2-1;t1++) { saf<<" ";}if(HF.ht[p].s==" "||HF.ht[p].s=="")saf<<"0";//如果为空,输出0elsesaf<<HF.ht[p].s;//否则输出字符q.pop();if(HF.ht[p].lchild!=-1)q.push(HF.ht[p].lchild);if(ht[p].rchild!=-1)q.push(HF.ht[p].rchild);t1+=2;}else{d++;saf<<endl;t1=0;t2=0;}}}//print(2*m_gcharnum-2,1,saf);*///以上容用于实现输出树到文本,树形,不是凹入树,只是效果不佳,下面的方法则是输出凹入树。

相关文档
最新文档