数据结构课程设计

 《数据结构课程设计书》

课程题目 哈弗曼编码与译码
课程编号 J1620102
学生姓名 曾秋巧
所在专业 信息管理与信息系统
所在班级 信管1132班
任课老师 易学明
实习时间 2015.1.8
设计成绩
老师评语




目     录
    
第一章 问题描述.....................................................................................3
第二章 问题分析.....................................................................................3
第三章 逻辑结构和存储结构设计.........................................................3
第四章 算法分析.....................................................................................3

第五章 时间复杂度和空间复杂度分析..................................................4
第六章 源代码..........................................................................................4
第七章 程序运行结果..............................................................................7
第八章 心得..............................................................................................9


第一章、问题描述
    在一个加密应用中,要处理的信息来自下面的字符集,各个字符的相关使用频度如下:
字符空格 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)输出解密字符串。
第二章、问题分析
   对字符集加密有多种方法,这里用的是哈弗曼编码对其进行加密。首先需要确定字符和权值,然后从权值中选择最小的两个构造根子树,以此类推,直到只剩下一棵树,便是哈弗曼树,将其左子树赋值为0,右子树赋值为1,对哈弗曼树进行遍历便可得到加密后的字符集。对字符集的解密则需要解读01串,0代表往左子树,1代表右子树,01串起到“路标”的作用,使之最后找到所属叶子即解密后的字符。
第三章、逻辑结构与存储结构设计
(1)逻辑结构设计:利用最优二叉树的叶子节点存储权值
(2)存储结构设计:利用链式存储结构存储,用链表表示一棵二叉树,即用链来表示逻辑关系。本文采用双亲孩子表示法,每个结点包含5个域,包括数据域,左右孩子,父母,权重。
第四章、算法分析
(1)从键盘输入结点值与权值
(2)给定n个带权的节点,如何构造一棵n个带有给定权值的叶节点的二叉树,使其带全路径长度WPL最小,构造最优树算法如下.
哈弗曼算法:
1. 将n个权值分别为w1,w2,w3,....wn-1,wn的节点按权值递增排序,将每个权值作为一棵二叉树构成n棵二叉树森林F={T1,T2,T3,T4,...Tn},其中每个二叉树都只有一个权值,其左右字数为空。
2. 在森林F中选取根节点权值最小二叉树,作为左右字数构成一棵新的二叉树,并使得新的二叉树的根节点为其左右字数权值之和,其中叶子都是最初的树。
3. 在森林F中删除这两棵树,同时将新得到的二叉树代替这两个树加入到森林F中,因此森林中二叉树的个数比以前少一颗。
4. 对新的森林重复2和3,直到森林中只有一棵树位置,这棵树就是哈夫曼树.
图一:




第五章、时间复杂度和空间复杂度分析
(1)时间复杂度:由于采取的是哈弗曼编码,构造哈弗曼树后,得到哈弗曼编码需要遍历每一个结点,在程序设计中共有26个结点,从根节点开始进行前序遍历,因此所花费的时间复杂度为O(n)。
(2)空间复杂度:空间复杂度是指程序运行所需要的内存空间,我们需要存放的有结点数据及关系,所以所需要内存空间为一个常数,所以空间复杂度为    O(1)。
第六章、源程序代码:
#include<iostream.h> 
#include<stdio.h> 
#include<malloc.h> 
#define N 25 //树叶从0开始,最大为25
typedef struct //定义结构体
{
char data;//哈弗曼树结点值
    int weight; //权重 
    int parent; //父母结点
    int lchild;  //左孩子
    int rchild; //右孩子
} HtNode; 
typedef struct//定义结构体
{     
char cd[N];  
    int begin; 
} HuffmanCode; 
int main()
{
HtNode Ht[2*N];  //结点有2*n个
    HuffmanCode hcd[N], d;  
int i, k, f, l, r, n, c, s1, s2; 
    cout<<" * * * * * * * * * * * * * * * * * * \n"      
   <<"       哈弗曼编码与译码系统\n" 
        <<" * * * * * * * * * * * * * * * * * * \n"; 
    cout<<"\n请输入要进行编码的元素个数:";
    cin>>n;  
    cout<<"请输入各个元素的结点值与权值:\n";//从键盘输入结点值与权值
for(i=1;i<=n;i++) 
{
cout<<"  第"<<i<<"个元素-->\n\t结点值:"; //对相应的点进行赋值
        cin>>&Ht[i].data;  
        cout<<"\t权值:";
        cin>>Ht[i].weight; 

for(i=1;i<=2*n-1;i++)//初始化结点
Ht[i].parent=Ht[i].lchild=Ht[i].rchild=0; 
for(i=n+1;i<=2*n-1;i++)  //从所给的权值中找出最小的两个构造哈弗曼树
{
s1=s2=40000;   
        l=r=0;
for(k=1;k<=i-1;k++)
if(Ht[k].parent==0)
if(Ht[k].weight<s1)

s2=s1;      
           r=l; 
                    s1=Ht[k].weight;      
l=k;    
}    
else if(Ht[k].weight<s2)     
{      
s2=Ht[k].weight;      
r=k;     
}
Ht[l].parent=i;  //设置两颗最小树的双亲   
Ht[r].parent=i;     
                Ht[i].weight=Ht[l].weight+Ht[r].weight; //设置这棵3节点的树的根的权值以及孩子    
Ht[i].lchild=l;    
                Ht[i].rchild=r;  

for(i=1;i<=n;i++)//左子树为0,右子树为1
{   
d.begin=n+1;  
c=i;   f=Ht[i].parent;   
while(f!=0)   
{
if(Ht[f].lchild==c)
d.cd[--d.begin]='0';    
else      
d.cd[--d.begin]='1';   
c=f;    
f=Ht[f].parent;  
}   
hcd[i]=d;  

cout<<"编码后的字符代码为:\n"; //输出编码后的代码
for(i=1;i<=n;i++)  
{   
cout<<Ht[i].data<<": ";   
for(k=hcd[i].begin;k<=n;k++)    
cout<<hcd[i].cd[k];   
cout<<"\n";  

a:cout<<"\n* * *请选择操作:* * *\n";
cout<<" b:编码  y:译码 e:退出系统  ";
  char hfm;  
  cin>>hfm;  
  if(hfm=='e')//退出系统 
 return 0;  
  else  
  {   
 switch(hfm)   
 {   
 case'b':    //继续进行编码
 {       
 int q ;    
 char bs;     
 cout<<"\n* * *   哈弗曼编码   * * *\n";     
 cout<<"请输入需要编码的字符:  ";    
 for(q=0;bs!=10;q++)     
 {      
 bs=getchar();      
 for(i=1;i<=n;i++)      
 {
 if (bs==Ht[i].data)       
 for(k=hcd[i].begin;k<=n;k++)
 cout<<"编码后的字符代码为:"<<hcd[i].cd[k];      
 }     
 }     
 cout<<endl;    
 } break;   
 case'y':    //进行译码(只能对已经编码的字符进行译码)
 {       
 char e;     
 int t,u;      
 t=2*n-1;     
 cout<<"\n* * *   哈弗曼译码   * * *\n";     
 cout<<"\n* * * 请输入哈弗曼码(0/1):  * *";     
 for(u=0;e!=10;u++)     
 {       
 if(Ht[t].lchild!=0)       
 {       
 e=getchar();        
 if(e=='0')         
 t=Ht[t].lchild;       
 else                     
 t=Ht[t].rchild;       
 }
 else       
 {   
 cout<<"输入的哈弗曼码的译码是:"<<Ht[t].data;        
 t=2*n-1;
 }     
 }
 cout<<endl;   
 } break;   
 } goto a; //返回到以a为标志的地方 
  } return 0; 





第七章、程序运行结果

从键盘输入结点值与权值:加密后的哈弗曼编码及其译码:


第八章、心得
在课程设计过程中,我认真研究,根据课堂讲授内容,借助书本,自己动手实践。不但有助于消化课堂所讲解的内容,还可以增强独立思考能力和动手能力;通过编写实验代码和调试运行,我们可以逐步积累调试C++程序的经验并逐渐培养我们的编程能力、用计算机解决实际问题的能力。在实验过程中,我们不但有自己的独立思考,还借助各种参考文献来帮助我们完成系统。更为重要的是,同学之间加强了交流,在对问题的认识方面可以交换不同的意见。通过这次实验让我们明白:作为一名大学生必须严格训练分析总结能力、书面表达能力。需要逐步培养书写科学实验报告以及科技论文的能力。只有这样,我们的综合素质才会有好的提高。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值