数据结构实验报告 文件压缩.docx

上传人:b****1 文档编号:15158489 上传时间:2023-07-01 格式:DOCX 页数:25 大小:90.79KB
下载 相关 举报
数据结构实验报告 文件压缩.docx_第1页
第1页 / 共25页
数据结构实验报告 文件压缩.docx_第2页
第2页 / 共25页
数据结构实验报告 文件压缩.docx_第3页
第3页 / 共25页
数据结构实验报告 文件压缩.docx_第4页
第4页 / 共25页
数据结构实验报告 文件压缩.docx_第5页
第5页 / 共25页
数据结构实验报告 文件压缩.docx_第6页
第6页 / 共25页
数据结构实验报告 文件压缩.docx_第7页
第7页 / 共25页
数据结构实验报告 文件压缩.docx_第8页
第8页 / 共25页
数据结构实验报告 文件压缩.docx_第9页
第9页 / 共25页
数据结构实验报告 文件压缩.docx_第10页
第10页 / 共25页
数据结构实验报告 文件压缩.docx_第11页
第11页 / 共25页
数据结构实验报告 文件压缩.docx_第12页
第12页 / 共25页
数据结构实验报告 文件压缩.docx_第13页
第13页 / 共25页
数据结构实验报告 文件压缩.docx_第14页
第14页 / 共25页
数据结构实验报告 文件压缩.docx_第15页
第15页 / 共25页
数据结构实验报告 文件压缩.docx_第16页
第16页 / 共25页
数据结构实验报告 文件压缩.docx_第17页
第17页 / 共25页
数据结构实验报告 文件压缩.docx_第18页
第18页 / 共25页
数据结构实验报告 文件压缩.docx_第19页
第19页 / 共25页
数据结构实验报告 文件压缩.docx_第20页
第20页 / 共25页
亲,该文档总共25页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

数据结构实验报告 文件压缩.docx

《数据结构实验报告 文件压缩.docx》由会员分享,可在线阅读,更多相关《数据结构实验报告 文件压缩.docx(25页珍藏版)》请在冰点文库上搜索。

数据结构实验报告 文件压缩.docx

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

 

数据结构与程序设计实验

实验报告

课程名称

数据结构与程序设计实验

课程编号

0906550

实验项目名称

文件压缩

学号

年级

姓名

专业

计算机科学与技术

学生所在学院

计算机学院

指导教师

杨静

实验室名称地点

21B276

哈尔滨工程大学

实验报告四

实验课名称:

数据结构与程序设计实验

实验名称:

文件压缩

班级:

学号:

姓名:

时间:

2016.04.21

一、问题描述

哈夫曼编码是一种常用的数据压缩技术,对数据文件进行哈夫曼编码可大大缩短文件的传输长度,提高信道利用率及传输效率。

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

统计待压缩的文本文件中各字符的词频,以词频为权值建立哈夫曼树,

并将该哈夫曼树保存到文件HufTree.dat中。

根据哈夫曼树(保存在HufTree.dat中)对每个字符进行哈夫曼编码,并

将字符编码保存到HufCode.txt文件中。

压缩:

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

解压:

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

二、数据结构设计

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

1.使用结构体数组统计词频,并存储:

typedefstructNode{

intweight;//叶子结点的权值

charc;//叶子结点

intnum;//叶子结点的二进制码的长度

}LeafNode[N];

2.使用结构体数组存储哈夫曼树:

typedefstruct{

unsignedintweight;//权值

unsignedintparent,LChild,RChild;

}HTNode,Huffman[M+1];//huffman树

3.使用字符指针数组存储哈夫曼编码表:

typedefchar*HuffmanCode[2*M];//haffman编码表

三、算法设计

1.读取文件,获得字符串

voidread_file(charconst*file_name,char*ch){

FILE*in_file=Fopen(file_name,"r");

unsignedintflag=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);

intlen=strlen(ch);

ch[len-1]='\0';

}

2.统计叶子结点的字符和权值并存储

voidCreateLeaf(charch[],int*ch_len,LeafNodeleaves,int*leaf_num){

intlen,j,k;

inttag;

*leaf_num=0;//叶子节点个数

//统计字符出现个数,放入CW

for(len=0;ch[len]!

='\0';len++){//遍历字符串ch[]

tag=1;

for(j=0;j

if(ch[j]==ch[len]){

tag=0;

break;

}

}

if(tag){//*leaf_num=0不用

leaves[++*leaf_num].c=ch[len];

leaves[*leaf_num].weight=1;

for(k=len+1;ch[k]!

='\0';k++)//在之后的字符串中累计权值

if(ch[len]==ch[k])

leaves[*leaf_num].weight++;//权值累加

}

}

*ch_len=len;//字符串长度

}

3.创建HuffmanTree,并存储

创建:

voidCreateHuffmanTree(Huffmanht,LeafNodew,intn){

inti,j;

ints1,s2;

//初始化哈夫曼树

for(i=1;i<=n;i++){

ht[i].weight=w[i].weight;

ht[i].parent=0;

ht[i].LChild=0;

ht[i].RChild=0;

}

for(i=n+1;i<=2*n-1;i++){

ht[i].weight=0;

ht[i].parent=0;

ht[i].LChild=0;

ht[i].RChild=0;

}

for(i=n+1;i<=2*n-1;i++){

for(j=1;j<=i-1;j++)

if(!

ht[j].parent)

break;

s1=j;//找到第一个双亲为零的结点

for(;j<=i-1;j++)

if(!

ht[j].parent)

s1=ht[s1].weight>ht[j].weight?

j:

s1;

ht[s1].parent=i;

ht[i].LChild=s1;

for(j=1;j<=i-1;j++)

if(!

ht[j].parent)

break;

s2=j;//找到第二个双亲为零的结点

for(;j<=i-1;j++)

if(!

ht[j].parent)

s2=ht[s2].weight>ht[j].weight?

j:

s2;

ht[s2].parent=i;

ht[i].RChild=s2;

ht[i].weight=ht[s1].weight+ht[s2].weight;//权值累加

}

}

存储:

voidsave_HufTree(Huffmanht,LeafNodele,intln){

inti;

FILE*HufTree=Fopen("HufTree.dat","a");

CreateHuffmanTree(ht,le,ln);

printf("\n哈夫曼树\n");

printf("编号权值parentLChildRChild\n");

//fputs("编号|权值|parent|LChild|RChild\n",HufTree);

for(i=1;i<=2*ln-1;i++){/*打印Huffman树的信息*/

printf("%d\t%d\t%d\t%d\t%d\n",

i,(ht)[i].weight,(ht)[i].parent,(ht)[i].LChild,(ht)[i].RChild);

fprintf(HufTree,"%d|%d|%d|%d|%d\n",

i,(ht)[i].weight,(ht)[i].parent,(ht)[i].LChild,(ht)[i].RChild);

}

Fclose(HufTree);

printf("哈弗曼树已保存至HufTree.dat\n");

}

4.读取哈夫曼树至新的结构体数组

voidread_HufTree(Huffmanht){//记得从1开始存储

inti=1,j;

FILE*HufTree=Fopen("HufTree.dat","r");

while((fscanf(HufTree,"%d|%d|%d|%d|%d\n",

&j,&((ht)[i].weight),&((ht)[i].parent),&((ht)[i].LChild),&((ht)[i].RChild)))==5){

//printf("%d\t%d\t%d\t%d\n",(ht)[i].weight,(ht)[i].parent,(ht)[i].LChild,(ht)[i].RChild);

i++;

}

Fclose(HufTree);

printf("已从HufTree.dat读取哈弗曼树\n");

}

5.根据哈夫曼树生成每个叶子结点的编码

voidCrtHuffmanNodeCode(Huffmanht,charch[],HuffmanCodecode_of_leaf,LeafNodeweight,intm,intn){

inti,c,p,start;

char*cd;

cd=(char*)malloc(n*sizeof(char));

cd[n-1]='\0';//末尾置0

for(i=1;i<=n;i++){

start=n-1;//cd串每次从末尾开始

c=i;

p=ht[i].parent;//p在n+1至2n-1

while(p){//沿父亲方向遍历,直到为0

start--;//依次向前置值

if(ht[p].LChild==c)//与左子相同,置0

cd[start]='0';

else//否则置1

cd[start]='1';

c=p;

p=ht[p].parent;

}

weight[i].num=n-start;//二进制码的长度(包含末尾0)

code_of_leaf[i]=(char*)malloc((n-start)*sizeof(char));

strcpy(code_of_leaf[i],&cd[start]);//将二进制字符串拷贝到指针数组code_of_leaf中

}

free(cd);//释放cd内存

}

6.保存每个叶子结点的信息

voidsave_HufCode(Huffmanht,char*ch,HuffmanCodecode_of_leaf,LeafNodeleaves,intch_len,intleaf_num){

inti;

FILE*HufCode=Fopen("HufCode.txt","a");

CrtHuffmanNodeCode(ht,ch,code_of_leaf,leaves,ch_len,leaf_num);//叶子结点的编码

printf("\n每个叶子节点的前缀码\n");//打印叶子结点的编码

for(i=1;i<=leaf_num;i++){

printf("%c:

%s\n",leaves[i].c,code_of_leaf[i]);

fprintf(HufCode,"%c:

%s\n",leaves[i].c,code_of_leaf[i]);

}

Fclose(HufCode);

printf("每个叶子节点的前缀码已保存至HufCode.txt\n");

}

7.读取每个叶子节点的信息到新的字符指针数组

voidread_HufCode(HuffmanCodecode_of_leaf){

inti=1;

charc,tem[10];

FILE*HufCode=Fopen("HufCode.txt","r");

while((fscanf(HufCode,"%c:

%s\n",&c,tem))==2){

intlen=strlen(tem);

code_of_leaf[i]=(char*)malloc(len*sizeof(char));

strcpy(code_of_leaf[i],tem);

//printf("%c:

%s\n",c,code_of_leaf[i]);

i++;

}

Fclose(HufCode);

printf("已从HufCode.txt读取每个叶子节点信息\n");

}

8.生成所有字符的编码

voidCrtHuffmanCode(charch[],HuffmanCodecode_of_leaf,HuffmanCodecode_of_ch,LeafNodeleaves,intleaf_num,intch_len){

inti,k;

for(i=0;i

for(k=1;k<=leaf_num;k++)/*从weight[k].c中查找与ch[i]相等的下标K*/

if(ch[i]==leaves[k].c)

break;

code_of_ch[i]=(char*)malloc((leaves[k].num)*sizeof(char));

strcpy(code_of_ch[i],code_of_leaf[k]);//拷贝二进制编码

}

}

9.保存字符串的编码信息(压缩)

FILE*Fopen(charconst*filename,charconst*mode){

FILE*idlist;

idlist=fopen(filename,mode);

if(idlist==NULL){

perror(filename);

exit(EXIT_FAILURE);

}else{

returnidlist;

}

}

10.解码并保存到str2.txt

voidTrsHuffmanTree(Huffmanht,LeafNodew,HuffmanCodehc,intn,intm){

inti=0,j,p;

FILE*str2=Fopen("str2.txt","a");

printf("\n经解压得原文件中的字符串:

");

while(i

p=2*n-1;//从父亲节点向下遍历直到叶子节点

for(j=0;hc[i][j]!

='\0';j++){

if(hc[i][j]=='0')

p=ht[p].LChild;

else

p=ht[p].RChild;

}

printf("%c",w[p].c);/*打印原信息*/

fputc(w[p].c,str2);

i++;

}

Fclose(str2);

printf("\n已将解压得到的字符串保存至str2.txt\n");

}

11.释放huffman编码内存

voidFreeHuffmanCode(HuffmanCodeh1,HuffmanCodeh2,HuffmanCodehc,intleaf_num,intch_len){

inti;

for(i=1;i<=leaf_num;i++){//释放叶子结点的编码

free(h1[i]);

free(h2[i]);

}

for(i=0;i

free(hc[i]);

}

四、运行测试与分析及运行界面

1.文件str1.txt内容:

2.运行程序,读取文件

3.统计叶子节点的权值

4.根据权值生成哈夫曼树,保存至HufTree.dat,并用新的结构体数组读取哈夫曼树

5.HufTree.dat内容

6.根据哈夫曼树生成叶子节点的前缀码,保存至HufCode.txt,之后用新的结构体数组读取HufCode.txt

7.HufCode.txt内容

8.根据前缀码生成哈夫曼编码,保存至CodeFile.dat

9.CodeFile.dat内容

10.根据CodeFile.dat解压,获得原字符串,并保存至str2.txt

11.str2.txt内容

五、实验收获与思考

通过使用哈夫曼树实现文件压缩,使我充分理解哈夫曼树的构造方法以及实际应用,巩固了课堂知识,同时认识到自己的不足。

在编程中发现问题,通过查询求助解决问题,使我不断地我加深数据结构的学习。

六、附录(原程序)

#include

#include

#include

#defineN100

#defineM2*N-1

typedefchar*HuffmanCode[2*M];//haffman编码

typedefstruct{

unsignedintweight;//权值

unsignedintparent,LChild,RChild;

}HTNode,Huffman[M+1];//huffman树

typedefstructNode{

intweight;//叶子结点的权值

charc;//叶子结点

intnum;//叶子结点的二进制码的长度

}LeafNode[N];

//产生叶子结点的字符和权值

voidCreateLeaf(charch[],int*ch_len,LeafNodeleaves,int*leaf_num){

intlen,j,k;

inttag;

*leaf_num=0;//叶子节点个数

//统计字符出现个数,放入CW

for(len=0;ch[len]!

='\0';len++){//遍历字符串ch[]

tag=1;

for(j=0;j

if(ch[j]==ch[len]){

tag=0;

break;

}

}

if(tag){//*leaf_num=0不用

leaves[++*leaf_num].c=ch[len];

leaves[*leaf_num].weight=1;

for(k=len+1;ch[k]!

='\0';k++)//在之后的字符串中累计权值

if(ch[len]==ch[k])

leaves[*leaf_num].weight++;//权值累加

}

}

*ch_len=len;//字符串长度

}

//创建HuffmanTree

voidCreateHuffmanTree(Huffmanht,LeafNodew,intn){

inti,j;

ints1,s2;

//初始化哈夫曼树

for(i=1;i<=n;i++){

ht[i].weight=w[i].weight;

ht[i].parent=0;

ht[i].LChild=0;

ht[i].RChild=0;

}

for(i=n+1;i<=2*n-1;i++){

ht[i].weight=0;

ht[i].parent=0;

ht[i].LChild=0;

ht[i].RChild=0;

}

for(i=n+1;i<=2*n-1;i++){

for(j=1;j<=i-1;j++)

if(!

ht[j].parent)

break;

s1=j;//找到第一个双亲为零的结点

for(;j<=i-1;j++)

if(!

ht[j].parent)

s1=ht[s1].weight>ht[j].weight?

j:

s1;

ht[s1].parent=i;

ht[i].LChild=s1;

for(j=1;j<=i-1;j++)

if(!

ht[j].parent)

break;

s2=j;//找到第二个双亲为零的结点

for(;j<=i-1;j++)

if(!

ht[j].parent)

s2=ht[s2].weight>ht[j].weight?

j:

s2;

ht[s2].parent=i;

ht[i].RChild=s2;

ht[i].weight=ht[s1].weight+ht[s2].weight;//权值累加

}

}

//生成每个叶子结点的编码

voidCrtHuffmanNodeCode(Huffmanht,charch[],HuffmanCodecode_of_leaf,LeafNodeweight,intm,intn){

inti,c,p,start;

char*cd;

cd=(char*)malloc(n*sizeof(char));

cd[n-1]='\0';//末尾置0

for(i=1;i<=n;i++){

start=n-1;//cd串每次从末尾开始

c=i;

p=ht[i].parent;//p在n+1至2n-1

while(p){//沿父亲方向遍历,直到为0

start--;//依次向前置值

if(ht[p].LChild==c)//与左子相同,置0

cd[start]='0';

else//否则置1

cd[start]='1';

c=p;

p=ht[p].parent;

}

weight[i].num=n-start;//二进制码的长度(包含末尾0)

code_of_leaf[i]=(char*)malloc((n-start)*sizeof(char));

strcpy(code_of_leaf[i],&cd[start]);//将二进制字符串拷贝到指针数组code_of_leaf中

}

free(cd);//释放cd内存

}

//生成所有字符的编码

voidCrtHuffmanCode(charch[],HuffmanCodecode_of_leaf,HuffmanCodecode_of_ch,LeafNodeleaves,intleaf_num,intch_len){

inti,k;

for(i=0;i

for(k=1;k<=leaf_num;k++)/*从weight[k].c中查找与ch[i]相等的下标K*/

if(ch[i]==leaves[k].c)

break;

code_of_ch[i]=(char*)malloc((leaves[k].num)*sizeof(char));

strcpy(code_of_ch[i],code_of_leaf[k]);//拷贝二进制编码

}

}

FILE*Fopen

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > PPT模板 > 自然景观

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2