大数据结构实验报告材料哈夫曼编码加密文件资料资料资料.docx
《大数据结构实验报告材料哈夫曼编码加密文件资料资料资料.docx》由会员分享,可在线阅读,更多相关《大数据结构实验报告材料哈夫曼编码加密文件资料资料资料.docx(18页珍藏版)》请在冰豆网上搜索。
![大数据结构实验报告材料哈夫曼编码加密文件资料资料资料.docx](https://file1.bdocx.com/fileroot1/2023-1/28/24ee9c34-dbf9-485e-838a-a29ddd06bc32/24ee9c34-dbf9-485e-838a-a29ddd06bc321.gif)
大数据结构实验报告材料哈夫曼编码加密文件资料资料资料
《数据结构》
实验报告
题目:
利用哈夫曼编码给文件或者文字加密
班级:
xxxx
学号:
xxxxxxxxxxx
姓名:
xxx
完成时间:
2010年12月19日
任课教师:
xxx
一、
问题描述
用哈夫曼编码,将输入的文字,或者文件中的文字进行编码,并输出加密后的文字。
二、
主程序
main
程序总体结构
显示界面告诉用户程序名称
show()
给用户提供选择方式
chioce1()
显示系统时间
showtime()
打开文件进行加密
openfile()
退出程序
输入电文进行加密
input()
统计输入(文件中)字母的出现频率
CrW(data,w,count)【fcount(alldata,data,count)】
将输入(文件中)的电文创建成哈夫曼树
CrtHuffmantree(ht,w,n)
将输入(文件中)的电文进行哈夫曼编码
CrtHuffmanCode(ht,hc,n)
输出每一个字母所对应的哈夫曼编码
Printf(hc,n,data,alldata,count)
对输入(文件中)的文字进行哈夫曼加密
showall(hc,alldata,count,data,n)
1、数据结构
此函数中运用到的数据结构知识就是哈夫曼树的建立以及遍历,建立主要就是每一次选择权值最小的两个数并将其求和,然后用他们的和代替这两个数,再进行求两个最小值,最后构成一个哈夫曼数;遍历是采用从叶子结点开始向根节点确定唯一的路径。
2、主要函数:
(1)voidCrtHuffmantree(HuffmanTree&ht,intw[],intn),功能是建立一个哈夫曼树;
(2)voidCrtHuffmanCode(HuffmanTreeht,HuffmanCodehc,intn),功能是计算哈夫曼编码;
(3)voiddianwen(intcount[],charalldata[]),功能是统计输入电文的字母种类以及频率;
(4)intfcount(charalldata[],chardata[],intcount[]),功能是统计打开文件中出现的字母的种类以及频率;
(5)voidshowtime(),功能是查看系统当前的时间;
(6)intsearch(charch,chardata[],intn),查询电文中的每一个字母所对应得哈夫曼编码的下标;
(7)voidPrintf(HuffmanCode&hc,intn,chardata[],charalldata[],intcount[]),功能是输出每一个字母所对应的哈夫曼编码;
(8)voidshowall(HuffmanCodehc,charalldata[],intcount[],chardata[],intn),功能是输出经过加密后的密文。
三、源代码
#include
#include
#include
#include
#defineN27//定义最大叶子结点个数
#defineM2*N-1
typedefstruct//定义哈夫曼结构体
{
intweight;
intparent;
intLChild;
intRChild;
}HTNode,HuffmanTree[M+1];//0号单元不用
typedefchar*HuffmanCode[N+1];//存储哈夫曼编码串的头指针
//调用系统的时间
voidshowtime()
{
time_tt;
tm*tp;
t=time(NULL);
tp=localtime(&t);
printf("\n\n\t\t\t%d/%d/%d\n",tp->tm_mon+1,tp->tm_mday,tp->tm_year+1900);
printf("\n\t\t\t%d:
%d:
%d\n",tp->tm_hour,tp->tm_min,tp->tm_sec);
}
//**************计算电文中各个英文字母出现的次数*******************
voiddianwen(intcount[],charalldata[])
{
intn,i;
printf("〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓");
printf("\n\n\n\t\t\t\t请输入电文:
\n");
fflush(stdin);
for(i=0;i<27;i++)//将数组计数器初始化
count[i]=0;
printf("%c",7);
alldata[0]=getchar();
while(alldata[count[0]]!
='\n')
{
n=(alldata[count[0]]-'a')+1;
count[n]++;
count[0]++;//所有字母的总个数
alldata[count[0]]=getchar();
}
}
voidCrW(chardata[],intw[],intcount[])//存储数据以及权值信息
{
inti,j;
j=0;
for(i=1;i<=26;i++)
{
if(count[i]!
=0)
{
j++;
data[j]=char(i-1+'a');
w[j]=count[i];
}
}
w[0]=j;//用于存储字母出现的种类个数
}
voidselect(HuffmanTree&ht,intn,int&s1,int&s2)//查找一串数字中的两个最小值
{
inti,t;
s1=0;
s2=0;
ht[0].weight=65535;
for(i=1;i<=n;i++)
{
if(ht[i].weight{
t=s1;
s1=i;
if(ht[t].weight{
s2=t;
}
}
elseif(ht[i].weights2=i;
else;
}
}
voidCrtHuffmantree(HuffmanTree&ht,intw[],intn)//创建哈夫曼树
{
inti,m;
ints1,s2;
for(i=1;i<=n;i++)//初始化叶子结点
{
ht[i].weight=w[i];
ht[i].parent=0;
ht[i].LChild=0;
ht[i].RChild=0;
}
m=2*n-1;
for(i=n+1;i<=m;i++)//初始化其他结点
{
ht[i].weight=0;
ht[i].parent=0;
ht[i].LChild=0;
ht[i].RChild=0;
}
for(i=n+1;i<=m;i++)
{
select(ht,i-1,s1,s2);
ht[i].weight=ht[s1].weight+ht[s2].weight;
ht[s1].parent=i;
ht[s2].parent=i;
ht[i].LChild=s1;
ht[i].RChild=s2;
}
}
//计算哈夫曼编码
voidCrtHuffmanCode(HuffmanTreeht,HuffmanCodehc,intn)
{
inti,start,c,p;
char*cd;
cd=(char*)malloc((n+1)*sizeof(char));
cd[n-1]='\0';
for(i=1;i<=n;i++)
{
start=n-1;
c=i;
p=ht[i].parent;
while(p!
=0)
{
--start;
if(ht[p].LChild==c)cd[start]='0';
elsecd[start]='1';
c=p;
p=ht[p].parent;
}
hc[i]=(char*)malloc((n-start)*sizeof(char));
strcpy(hc[i],&cd[start]);
}
free(cd);
}
//查找字母所对应的哈夫曼编码
intsearch(charch,chardata[],intn)
{
inti;
for(i=1;i<=n;i++)
{
if(ch==data[i])
returni;
elsei++;
}
return1;
}
//显示所有文字的哈夫曼编码
voidshowall(HuffmanCodehc,charalldata[],intcount[],chardata[],intn)
{
inti,m;
system("cls");
printf("〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓\n\n");
printf("\t\t\t所有电文经过哈夫曼编码加密之后如下\n%c",7);
printf("\n\n◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆");
for(i=0;i{
m=search(alldata[i],data,n);
printf("%s",hc[m]);
}
printf("\n◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆\n\n");
system("pause");
}
//输出哈夫曼编码
voidPrintf(HuffmanCode&hc,intn,chardata[],charalldata[],intcount[])
{
inti;
system("cls");
printf("\n\n★★★各个字母所对应的哈夫曼编码★★★\n\n%c",7);
for(i=1;i<=n;i++)
{
printf("\t字母%c对应的哈夫曼码为:
",data[i]);
puts(hc[i]);
}
printf("\n\n★★★各个字母所对应的哈夫曼编码★★★\n\n");
printf("\n\n按任意键查看所有文字的加密结果……\n\n");
system("pause");
showall(hc,alldata,count,data,n);//查看文字的加密结果
}
//首界面窗口界面美化工作
voidshow()
{
inti;
printf("\n\n\n%c",7);
for(i=0;i<30;i++)
printf("%c=",2);
printf("\n\n\n\t\t欢迎使用哈夫曼编码加密系统\n\n\n");
for(i=0;i<30;i++)
printf("%c=",2);
printf("\n\n\t\t");
system("pause");
system("cls");
}
//输入文字加密
voidinput()
{
charalldata[1000];
intn,w[N];//w[]用于存储所出现的字母频率,w[0]用于存储出现字母种类的个数
intcount[27];//用于存储所有字母出现的频率,count[0]用于存储字母的总个数
chardata[N];//用于存储所出现过的字母
HuffmanTreeht;
HuffmanCodehc;
dianwen(count,alldata);
CrW(data,w,count);
n=w[0];
CrtHuffmantree(ht,w,n);
CrtHuffmanCode(ht,hc,n);
Printf(hc,n,data,alldata,count);
}
//计算文件中每一个字母出现的频率
intfcount(charalldata[],chardata[],intcount[])
{
inti=0,k=0,n,j;
HuffmanTreeht;
HuffmanCodehc;
for(j=0;j<27;j++)
count[j]=0;
while(alldata[i]!
='\0')
{
n=alldata[i]-'a'+1;
count[n]++;//统计每一个字符出现的频率
data[n]=char(n-1+'a');
count[0]++;//统计文件中字母的总个数
i++;
}
for(j=0;j<27;j++)
{
if(count[j]==0)
{
k++;
}
if(k!
=0&&count[j]!
=0)
{
count[j-k]=count[j];
count[j]=0;
k++;
}
}
n=26-k;
CrtHuffmantree(ht,count,n);
CrtHuffmanCode(ht,hc,n);
Printf(hc,n,data,alldata,count);
return0;
}
//打开文件加密
voidopenfile()
{
FILE*fp;
charalldata[1000];
intcount[27],i=0;
chardata[N];
charstname[20];
for(i=0;i<21;i++)
printf("%c%c",1,2);
printf("\n\n\n\t请输入文件名:
%c",7);
scanf("%s",&stname);
if((fp=fopen(stname,"r"))==NULL)
{
printf("文件打开失败!
\n");
exit(0);
}
system("cls");
printf("〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓");
printf("\n\n\t\t\t\t文件中的电文如下:
\n\n%c",7);
while(!
feof(fp))
{
fscanf(fp,"%s",&alldata);
printf("%s\n\n\n",alldata);
}
printf("〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓");
printf("\n\n\t\t请按任意键查看电文中字母的哈夫曼编码……\n\n\t\t\t");
system("pause");
fcount(alldata,data,count);
if(fclose(fp))
{
printf("不能关闭文件!
\n");
exit(0);
}
}
//提醒用户的选择1
voidchioce1()
{
intn,i;
printf("%c",7);
for(i=0;i<21;i++)
printf("%c%c",1,2);
printf("\n\n\t★1、打开本地文件加密\n\t★2、输入文字加密\n\t★0、退出\n\n");
for(i=0;i<21;i++)
printf("%c%c",1,2);
printf("\n\n\n\t请输入你的选择:
");
scanf("%d",&n);
while(n!
=0&&n!
=1&&n!
=2)
{
printf("%c",7);
printf("\n\n◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎\n");
printf("你的输入有误!
请重新输入!
");
printf("\n◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎\n\n");
printf("\n\n\t请输入你的选择:
");
scanf("%d",&n);
}
system("cls");
switch(n)
{
case1:
openfile();break;
case2:
input();break;
case0:
printf("\n\n\n\n\t\t\t%c欢迎再次使用!
再见……\n\n\n",7);return;
}
}
//main函数
intmain()
{
showtime();
show();
chioce1();
return0;
}
四、测试及结果
1、测试情况
这个程序中的创新之处就在于:
(1)调用系统的时间;
(2)将输入的英文字母进行直接统计,节省了时间以及内存;(3)复习了文件的使用,可以从当地文件中打开电文进行加密;(4)打开文件后需要统计所出现的英文字母的种类以及频率,需要根据字母所对应的ASCII码直接存储到相对应得位置(例如字母s,则它存储位置的下标就应该是's'-'a'+1);(5)存储完打开文件的信息之后,数组中可能出现0的情况(即电文中不出现某一个字母),需要在原来的数组上进行调整,并且要用时间、空间最小的方法,于是我变新设一个变量用于统计两个出现过的字母之间的距离,然后进行移位【for(j=0;j<27;j++){if(count[j]==0){k++;}
if(k!
=0&&count[j]!
=0){count[j-k]=count[j];count[j]=0;k++;}}】;(6)在电文进行输出加密后的文字时,需要读取电文中的每一个字母,并且根据字母进行计算其哈夫曼编码,这就需要查找这个字母所对应的哈夫曼编码的下标,易知哈夫曼编码所存储位置的下标要小于【'letter'-'a'+1】,可以从后向前查找,以节省时间;(7)、界面的美化,利用一些符号以及system("pause")【暂停】、system("cls")【清屏】、printf("%c",7)【发声音】等操作美化用户界面。
2、结果
(1)、初始界面:
(2)、选择界面:
(3)、选择错误时:
(4)、选择打开本地文件:
(5)、查看文件中每一个字母所对应的哈夫曼编码:
(6)、查看加密后的电文:
(7)、输入电文进行加密:
(8)、计算出来的哈夫曼编码:
(9)、输入电文经过加密后的结果:
五、总结与提高
经过这个实验的编写,我收获很多:
(1)、熟练的掌握了哈夫曼树的建立,以及哈夫曼编码用程序是如何的求出来的,并且知道了哈夫曼编码在现实生活中的用途;
(2)、经过上网查询出了一些没有学过的知识:
时间函数的调用,增加了自己对时间函数的理解,掌握了一些基本的时间函数知识;
(3)、声音的输出,这个也是我第一次用C实现,虽然是“滴”的一声,但是,让我明白了计算机的ASCII码的更多知识;
(4)、在这个程序中有很多处,我为了节省空间以及缩短程序运行的时间,而思考算法,这是我学习数据结构之后所积淀下来的习惯,任何一个程序要尽自己的全力将算法做到最简,将运行时间做到最短、将占用空间做到最小。