数据结构课程设计第三题。
来源:互联网 发布:网络电影女演员 编辑:程序博客网 时间:2024/04/26 14:17
一·课程设计题目:
题目3.在一个加密应用中,要处理的信息来自下面的字符集,各个字符的相关使用频度如下:
字符空格 A B C D E F G H I J K L M
频度 180 64 13 23 32103 22 15 47 57 1 5 31 20
字符 N O P Q R S T U V W X Y Z
频度 55 63 15 1 48 56 80 25 7 18 2 16 1
现请编写程序你实现如下功能:
(1)运行时,由用户输入来初始化字符集大小和相应用字符。
(2)输入一个要加密的字符串,将其加密。
(3)输出解密字符串。
二·分析:
1.本题目要使自定义的字符集最快地获得一组编码,同时要防止数据的冗余,可以确定要使用哈夫曼编码,题目可以看成为:从键盘任意输入字符集,统计字符的频度并建立哈夫曼树,输出哈夫曼编码。
哈夫曼树的原理就是在给定的N个实数中(N≥2),带权路径长度最小的二叉树就是哈夫曼树,即所有的叶结点的权值乘上其到根结点的路径长度,用公式表达就是L=W1*L1+W2*L2+W3*L3+...+Wn*Ln。根据字符出现的概率来构造平均长度最短的编码。它是一种变长的编码。在编码中,若各码字长度严格按照码字所对应符号出现概率的大小的逆序排列,则编码的平均长度是最小的。(其长度因符号出现的概率而不同,所以说哈夫曼编码是变长的编码。)
在构造哈夫曼编码时,将哈夫曼树树中左分支和右分支分别标记为0和1;将从根到叶子的路径上的标号依次相连,作为该叶子所表示字符的编码。该编码即为哈夫曼编码。
2.加密和解密
有了字符集的哈夫曼编码表之后,对数据文件的编码过程是:依次读人文件中的字符c,在哈夫曼编码表H中找到此字符,若H.ch=c,则将字符c转换为H.bits中存放的编码串。
对压缩后的数据文件进行解码则必须借助于哈夫曼树T,其过程是:依次读人文件的二进制码,从哈夫曼树的根结点(即T[m-1])出发,若当前读人0,则走向左孩子,否则走向右孩子。一旦到达某一叶子T时便译出相应的字符H.ch。然后重新从根出发继续译码,直至文件结束。
3.源程序解析
用宏定义,定义了N为27,表示27个字符;M为2×N-1,表示huffman树的结点个数。定义了关于huffman的几个结构,见程序注释。为了方便,定义了一些关于huffman树、huffman编码的外部变量。
三·源程序:
#include<stdio.h>
#defineN27 //空格+26个大写字母
#defineM2*N-1
#defineinfinity32767 //宏定义
structnode //huffman树的结点结构
{
intweight; //结点权值
intplink,llink,rlink; //双亲,左孩子,右孩子
};
structcodetype //huffman编码结构
{
intstart; //起始位置
charbits[N+1]; //存放0,1的数组
};
structelement //字符及其编码的结构
{
charsymbol; //字符
structcodetype code; //字符编码
};
structnodetree[M+1]; //n个结点的huffman树
structelementtable[N+1],t[100]; //n个结点的huffman编码表,报文编码
int x1,x2;
void sethuftree(); //有关函数声明
void select0(ints);
void sethufcode();
void setcode();
void printtree();
void printhufcode();
void main() //**********主函数**********
{
sethuftree();
printtree();
sethufcode();
printhufcode();
setcode();
printf("\n\n");
}
void sethuftree() //建立huffuman树
{
inti,treeweight[N]={180,64,13,23,32,103,22,15,47,57,1,5,32,20,55,63,15,1,48,56,80,25,7,18,2,16,1};
chartablesymbol[N]={' ','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
for(i=1;i<=M;i++) //初始双亲,左,右结点为:0
tree[i].plink=tree[i].llink=tree[i].rlink=0;
for(i=1;i<=N+1;i++) //初始化27个字符及其权值
{
table[i].symbol=tablesymbol[i-1];
tree[i].weight=treeweight[i-1];
}
for(i=N+1;i<=M;i++) //找权值最小的2个结点,组成huffman树
{
select0(i-1); //调用找权值最小的2个结点函数
tree[x1].plink=i;
tree[x2].plink=i;
tree[i].llink=x1;
tree[i].rlink=x2;
tree[i].weight=tree[x1].weight+tree[x2].weight;
}
}
void select0(ints) //找权值最小的2个结点
{
inti;
floatv1,v2;
v1=v2=infinity;
x1=x2=0;
for(i=1;i<=s;i++)
if(tree[i].plink==0)
if(tree[i].weight<v1)
{
v2=v1;
x2=x1;
v1=tree[i].weight;
x1=i;
}
elseif(tree[i].weight<v2)
{
v2=tree[i].weight;
x2=i;
}
}
void printtree() //输出huffman树
{
inti;
printf("哈夫曼树为:\n\n");
printf("结点值权值(频度)双亲 左孩子 右孩子\n");
for(i=1;i<=N;i++)
printf(" %-8c%-11d%-8d%-8d%d\n",table[i].symbol,tree[i].weight,tree[i].plink,tree[i].llink,tree[i].rlink);
for(i=N+1;i<=M;i++)
printf("\t %-11d%-8d%-8d%d\n",tree[i].weight,tree[i].plink,tree[i].llink,tree[i].rlink);
printf("\n\n------------------------------------------------------------------\n\n\n");
}
void sethufcode() //建立huffman编码
{
inti,s,f,k=1;
structcodetype c;
for(i=1;i<=N;i++)
{
c=table[i].code;
c.start=N+1;
s=i;
f=tree[s].plink;
do
{
c.start--;
if(s==tree[f].llink)
c.bits[c.start]='0';
else
c.bits[c.start]='1';
s=f;
f=tree[s].plink;
}while(f);
table[i].code=c;
}
}
void printhufcode() //输出huffman编码,即空格+26个大写字母
{
inti,j;
structcodetype c;
printf("编码为:\n");
for(i=1;i<=N;i++)
{
printf("%c:",table[i].symbol);
c=table[i].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf("\n");
}
printf("\n\n--------------------------------------------------------------------\n\n");
}
void setcode() //对报文进行编码
{
inti,j,count;
char c0,k='Y';
structcodetype c;
while(k=='Y') //利用循环,实现对报文多次编码
{
printf("\n\n请输入字符集(大写字母+空格,不超过100),输入'.'(+回车)号结束\n\n");
for(i=1;i<=100;i++) //利用循环,实现对报文输入
{
c0=getchar();
t[i].symbol=c0;
if(c0=='.')break;
}
count=i; //记录报文个数
printf("\n\n--------------------------------------------------------------------\n\n");
printf("\n\n输出的解密字符串为:\n\n");
for(i=1;i<=count;i++) //利用循环,实现对报文输出
{
if(t[i].symbol=='.')break;
else
switch(t[i].symbol) //利用开关语句,查找编码
{
case' ':
c=table[1].code;
for(j=c.start;j<=N;j++) //输出编码
printf("%C",c.bits[j]);
printf(" ");
break;
case'A':
c=table[2].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case'B':
c=table[3].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf("");
break;
case'C':
c=table[4].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case'D':
c=table[5].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case'E':
c=table[6].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case'F':
c=table[7].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case'G':
c=table[8].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case'H':
c=table[9].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case'I':
c=table[10].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case'J':
c=table[11].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case'K':
c=table[12].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case'L':
c=table[13].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case'M':
c=table[14].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf("");
break;
case'N':
c=table[15].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case'O':
c=table[16].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case'P':
c=table[17].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case'Q':
c=table[18].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case'R':
c=table[19].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case'S':
c=table[20].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case'T':
c=table[21].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case'U':
c=table[22].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case'V':
c=table[23].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case'W':
c=table[24].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case'X':
c=table[25].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case'Y':
c=table[26].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case'Z':
c=table[27].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
default:
printf(" *此编码找不到,请检查输入是否正确* ");
}
}
printf("\n\n\n--------------------------------------------------------------------\n\n");
printf("\n\n\n----- 是否继续?(Y/N) -----\n");
getchar();
printf("\n");
scanf("%c",&k);
getchar();
printf("\n\n*********************************************************\n\n");
}
}
四·总结
程序运行有三个部分:第1部分,为27个字符的huffman树;第2个部分,为huffman编码,第三部分为解密字符串。
五·体会
在熟练掌握二叉树的基础上理解哈夫曼树和哈夫曼编码,熟知二叉树的性质及哈夫曼树为什么没有度为1的节点,理解节电总数M与叶子节电之间的关系为2*N-1。
程序是在不断的摸索尝试中才能越来越熟练的,光靠书本上背语法之类的不能做出程序,这个程序也是,我在参考了网上的方法之后才知道用哈夫曼树加密解密的方法,书上有没有提我没有注意到,真正实践了才知道。
- 数据结构课程设计第三题。
- 数据结构课程设计第三题程序内容
- 山东大学软件学院数据结构课程设计第三题
- 课程设计(第三题)
- 数据结构课程设计 第四题
- 数据结构课程设计 题2
- 数据结构课程设计(题2)
- 数据结构课程设计
- 数据结构课程设计
- 课程设计----数据结构
- 数据结构课程设计
- 数据结构课程设计
- 数据结构课程设计
- 数据结构课程设计
- 数据结构课程设计
- 数据结构课程设计
- 《数据结构》课程设计
- 数据结构课程设计
- Python BeautifulSoup 简单笔记
- 转换整型数为BCD编码二进制数
- 全志A12和RK3128开发的安卓智能音响模具首版终于回来了
- 000 community service centres in the rural India to provide a broadband connectivity in 2008-09 The
- android摄像头获取图像——第三弹
- 数据结构课程设计第三题。
- Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥)
- 痘痘,多少事你不知道自己不知道?
- ssh两主机互信登录___代码实例
- Eclipse中跟踪调试Android源代码
- C++到Java的学习之路--初识java(一)变量初始化
- 【ExtJS】修复tree重复加载Bug
- MyEclipse10破解方法
- ExpandableListView用法实例