哈夫曼树课程设计论文
哈夫曼树的应用数据结构课程设计

《数据结构》课程设计报告题目:哈夫曼树应用学生姓名:谢辉学号: 201317010201专业班级:计科13102同组姓名:赵丽娜指导教师:徐晓蓉设计时间:2014年下学期第18周目录一、需求分析 (2)1. 分析问题 (2)2. 确定解决方案 (2)3. 输入的形式和输入值的范围 (3)4.输出的形式 (3)5.程序所能达到的功能 (3)二、概要设计 (4)1. 主程序的流程图: (4)2.程序中数据类型的定义: (4)3.各程序模块之间的层次(调用)关系: (4)三、详细设计 (5)1.哈夫曼树存储及类的定义: (5)2.哈夫曼树的基本操作: (6)3.主函数 (7)1. 测试数据及其输出结果: (9)2. 调试过程中遇到的问题及解决办法: (13)五、总结 (14)七、致谢 (14)八、附录 (14)一、需求分析1.分析问题利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。
但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。
对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。
为这样的信息收发站写一个哈夫曼码的编/译码系统。
2.确定解决方案设计建立带权的哈夫曼树,确定哈夫曼树的类与成员函数,以及各函数之间的调用关系,采用动态数组的存储结构存储所需要的数据,通过不同的函数来实现编码,译码以及打印二进制编码、哈夫曼树,把不同的数据存入不同的txt文件中,通过主函数调用来实现功能检测。
3.输入的形式和输入值的范围手动或者从文本中读入数据的形式初始化哈夫曼树,从键盘中或者文件中读入数据,以字母A-Z代表结点,以自然数代表权值,字符串提示使用者所要执行的操作。
4.输出的形式在显示器界面上或者以文本的形式来实现程序调试的输出。
5.程序所能达到的功能(1)I:初始化(Initialization)。
从终端读入字符集大小n,以及n个字符和n 个权值,建立哈夫曼树,并将它存于文件hfmTree中。
哈夫曼树毕业论文(修改版)

WPL
n
Wk L权值 ; Lk 为第 k 个叶结点的路径长度 . 现用下图 1.1.1解释上述相关概念
图 1.1.1
别是 Wi 和 Wj , 否则将 W1,W2 分别与 Wi ,Wj 互换 , 得到一棵树 , 但
W1L W1 W2 L W2 Wi L Wi Wj L W j 与 T 是哈夫曼树矛盾 .
(3) 首 先 可 知 W T W T W1 W2 . 假 设 T 不 是 哈 夫 曼 树 , T1 是 带 权
W1 W2, W3, ,Wn 的 哈 夫 曼 树 . 在 T 中 以 W1 W2 的 两 个 儿 子 W1 和 W2 为 树 叶 , W1 W2 成为分支点 , 得到一棵带权 W1,W2 , Wn 的二叉树 T2 , 则
的带权路径长度 . 那么如何找到带权路径长度最小的二叉树呢?根据哈夫曼树的 定义 , 一棵二叉树要使其 WPL 值最小 , 必须使权值越大的叶结点越靠近根结点 , 而权值越小的叶结点越远离根结点 , 这样计算树的带权路径长度时 , 自然树会具 有最小的带权路径长度 , 这是生成算法的一种基本思想 .
为了构造权值为 W1,W2,W3, ,Wn 的哈夫曼树 , 哈夫曼提出了一种构造算法 , 现将其陈述如下 : 步骤 1 根据题目给定的 n 个权值 W1,W2 ,W3, ,Wn 构造有下列 n 棵二叉树的集合
F T1,T2 ,T3, ,Tn , 其中每棵二叉树 Ti 中只有一个带权为 Wi 的根结点 , 其 左右树均为空 ; 步骤 2 在 F 中选取两棵根结点的权值最小的树作为左、右子树构造一棵新的二 叉树 , 且置新的二叉树的根结点的权值为其左、右子树上根结点的权值之 和; 步骤 3 在 F 中删除这两棵树 , 同时将新得到的二叉树加入 F 中 ; 步骤 4 重复步骤 2 和步骤 3, 直到 F 只含有一棵树为止 , 这棵树便是哈夫曼树 . 2.2 举例说明其构造过程
哈夫曼树课程设计报告c语言

哈夫曼树课程设计报告c语言哈夫曼树是广泛应用于数据压缩和编码的一种数据结构。
在计算机科学中,哈夫曼编码是一种无损的压缩算法,它基于使用较少的位数来表示频繁出现的字符,从而达到节省空间的目的。
本篇文章将围绕哈夫曼树的课程设计报告进行阐述,帮助读者更加深入地理解和应用哈夫曼树。
首先,我们需要了解哈夫曼树的基本概念和算法。
哈夫曼树是一种二叉树,它的每个节点都表示一个字符和它出现的频率。
哈夫曼树的算法主要是通过构建最小权重树来实现,即将输入的字符按照出现的频率进行排序,然后选择出现频率最小的两个字符,将它们合并成一个节点。
这个新节点的权重就是两个字符的权重之和。
继续将这个新节点与下一个最小频率字符继续合并,直到所有字符合并成一个节点。
最终形成的二叉树就是哈夫曼树。
接下来,我们需要学习如何在C语言中实现哈夫曼树。
在实现过程中,我们需要定义一个结构体来表示哈夫曼树节点。
这个结构体包含两个成员:字符和出现的频率。
同时,我们需要定义一个优先队列来存储字符节点和它们的权重。
在优先队列中,我们需要实现一些基本操作,比如插入、删除和取出队首元素等等。
通过这些操作,我们就可以按照字符频率构建出哈夫曼树。
最后,我们需要实现哈夫曼编码的功能。
在哈夫曼编码中,我们需要定义一个数组来存储每个字符的编码。
这个数组的索引是字符的ASCII码,它的值是该字符的哈夫曼编码。
在对输入字符串进行编码时,我们从哈夫曼树的根节点开始,按照左右子树的方向进行编码。
当遇到叶子节点时,我们就将编码添加到输出字符串中。
最终,我们就可以完成对字符串的压缩和解压。
综上所述,哈夫曼树是一种非常有用的数据结构,它在数据压缩和加密领域都有广泛的应用。
通过本篇文章的介绍,希望读者们能够更加深入地理解哈夫曼树的基本概念和实现方法。
在学习过程中,读者们也可以尝试自己动手实现哈夫曼树,并应用到实际的项目中,提高自己的编程能力。
哈夫曼树的课程设计报告

数据结构与算法课程设计报告书题目:哈夫曼编码/译码器班级:学号:1109121105姓名:田欢指导教师:龚丹周期:2011-12-19至2011-12-23成绩:年月日一、课程设计的目的与要求(一)课程设计目的与任务(参考已发文档自行编辑,但不少于100字)设计一个利用哈夫曼算法的编码和译码系统,重复地显示并处理以下项目,直到选择退出为止。
利用哈夫曼树编码问题基本原理的应用,撑握对树的不同存储结构的定义和算法描述。
学会构造哈夫曼树和哈夫曼编码等主要算法。
(二)题目要求1) 将权值数据存放在数据文件(文件名为data.txt,位于执行程序的当前目录中)2) 分别采用动态和静态存储结构3) 初始化:键盘输入字符集大小n、n个字符和n个权值,建立哈夫曼树;4) 编码:利用建好的哈夫曼树生成哈夫曼编码;5) 输出编码;6) 设字符集及频度如下表:字符空格A B C D E F G H I J K L M频度186 64 13 22 32 103 21 15 47 57 1 5 32 20字符N O P Q R S T U V W X Y Z频度57 63 15 1 48 51 80 23 8 18 1 16 1二、设计正文1 系统分析(1)定义一个变量名为HTNode的结构体,用该结构体中的char data、int weight、int parent、int lchild、int rchild分别表示哈夫曼树中每个结点的权值、权重、双亲结点、左孩子、右孩子,再定义一个HTNode类型的数组ht[30]存放哈夫曼树;另外定义一个变量名为HCode的结构体,采用HCode类型变量的cd[start]~cd[n]存放当前结点的哈夫曼编码、最后定义一个HCode类型的数组hcd[30]的数组用于存放当前叶子结点ht[i]的哈夫曼编码。
(2)编写CodeInput(n,ht)函数并在函数中设置一个for(i=0;n;++)循环,首先输入n个字符,再利用函数中的for(i=0;<n;++)循环实现对这n个字符的权值的输入。
哈夫曼树数据结构课程设计

计算机科学与技术系课程设计报告2013 ~2014 学年第 2 学期课程数据结构与算法课程设计名称哈夫曼树学生姓名xxx学号xxxx专业班级12软件工程指导教师xx一、题目设计程序以实现构造哈夫曼树的哈夫曼算法。
要求:求解所构造的哈夫曼树的带全路径长度。
二、问题分析和任务定义这个程序需要我们解决两个问题,第一个是构造哈夫曼树,第二个是求带权路径的长度。
本问题的关键就是在于如何建立哈夫曼树三、概要设计和数据结构选择假设给定n个实数w1,w2.....构造拥有n个叶子结点的哈夫曼树,且这n个叶子结点的权值分别为给定的实数,则哈夫曼树的构造方法如下:1.根据给定的n个实数,根据n颗单结点二叉树,各二叉树的根权值分别为w1,w2.......,令这n颗二叉树构成一个二叉树的集合M。
在这n颗单结点的二叉树中,这些结点既是根结点又是叶子结点。
2.在集合M中筛选出两个根结点的权值最小的二叉树作为左右子树,构造一颗新二叉树,且新二叉树根结点的权值为其左右子树根结点权值之和。
3.从集合M中删除被选取的两颗二叉树,并将新二叉树加入该集合。
4.重复2,3步,直到集合M中只剩一颗二叉树为止,则该二叉树即为哈夫曼树。
带权路径长度的计算,我们可以用一个简便的方法,即WPL等于哈夫曼树上非叶子结点权值之和。
一颗有n个叶子结点的哈夫曼树上共有2n-1个结点,可以采用长度为2n-1的数组顺序存储结点信息。
每一个结点应该包括四个域:存放该结点权值weight域,分别存放其左右孩子结点在数组中下标的lchild域和rchild,和记录该结点的父亲结点信息的parent 域。
所以我们定义的结点类型如下:typedef struct{float weight;int parent,lchild,rchild;}hufmtree;四、详细设计和编码基于上述存储结构的哈夫曼算法分析如下:1.初始化数组tree[2n-1];读入给定的n个权值,分别放入数组前n个分量的weight 域中,并将数组中所有分量的lchild域,rchild域和parent域置0.for(i=0;i<m;i++){ //初始化数组tree[i].parent=0;tree[i].lchild=0;tree[i].rchild=0;tree[i].weight=0.0;}2.从数组的前n个分量中选择权值最小和次小的两个结点(假设下标分别为p1和p2)合并,产生新结点。
课程设计(哈夫曼树)

计算机学院信息管理与信息系统专业数据结构课程设计题目:哈夫曼树的应用班级:姓名:学号:同组人姓名:起迄日期:课程设计地点:指导教师:完成日期:目录1、设计目的 (3)2、需求分析 (3)2.1选题的意义及背景 (3)2.2输入/输出形式和输出值的范围 (4)3、概要设计 (4)3.1设计思想 (4)3.2函数间的关系 (4)4、详细设计 (4)4.1哈夫曼的主要结构 (4)4.1.1结构定义 (4)4.1.2主要函数声明及功能描述 (5)4.2源程序 (6)4.2.1头文件 (6)4.2.2源文件 (7)5、程序测试结果 (15)6、总结 (16)7、参考文献 (16)1.设计目的数据结构作为一门学科主要研究数据的各种逻辑结构和存储结构,以及对数据的各种操作。
因此,主要有三个方面的内容:数据的逻辑结构;数据的物理存储结构;对数据的操作(或算法)。
通常,算法的设计取决于数据的逻辑结构,算法的实现取决于数据的物理存储结构。
数据结构是信息的一种组织方式,其目的是为了提高算法的效率,它通常与一组算法的集合相对应,通过这组算法集合可以对数据结构中的数据进行某种操作。
在当今信息时代,信息技术己成为当代知识经济的核心技术。
我们时刻都在和数据打交道。
比如人们在外出工作时找最短路径,在银行查询存款、通过互联网查新闻、以及远程教育报名等,所有这些都在与数据发生关系。
实际上,现实世界中的实体经过抽象以后,就可以成为计算机上所处理的数据。
数据结构课程主要是研究非数值计算的程序设计问题中所出现的计算机操作对象以及它们之间的关系和操作的学科。
数据结构是介于数学、计算机软件和计算机硬件之间的一门计算机专业的核心课程,它是计算机程序设计、数据库、操作系统、编译原理及人工智能等的重要基础,广泛的应用于信息学、系统工程等各种领域。
学习数据结构是为了将实际问题中所涉及的对象在计算机中表示出来并对它们进行处理。
通过课程设计可以提高学生的思维能力,促进学生的综合应用能力和专业素质的提高。
数据结构课程设计-哈夫曼树

嘉应学院计算机学院实验报告课程名称:数据结构课程设计开课学期:2017-2018学年第2学期班级:指导老师:实验题目:哈夫曼树学号:姓名:上机时间:一、实验目的本实验的目的是通过对简单的哈夫曼编/译码系统的设计与实现来熟练掌握树形结构在实际问题中的应用。
二、实验问题描述利用哈夫曼编码进行通信可以大大提高通信利用率,缩短信息传输时间,降低传输成本。
但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码,此试验即设计这样的一个简单的编/译码系统。
系统应该具备如下的几个功能。
1、求出各个叶子节点的权重值输入一个字符串,统计其中各个字母的个数和总的字母个数。
2、构造哈夫曼树统计出的字母种类为叶子结点个数,每个字母个数为相应的权值,建立哈夫曼树。
3、打印哈弗曼树的功能模块按照一定形式打印出哈夫曼树。
4、编码利用已经建立好的哈夫曼树进行编码。
5、译码根据编码规则对输入的代码进行翻译并将译码。
三、实验步骤1、实验问题分析(1)设计一个结构体数组保存字母的类型和个数。
{; 字母的种类; 字母的个数};(2)在构造哈夫曼树时,设计一个结构体数组保存哈夫曼树中各结点的信息,根据二叉树的性质可知,具有n个结点的哈夫曼树共有21个结点,所以数组大小设置为21,描述结点的数据类型为:{; 权值; 双亲; 左孩子; 右孩子};[]; 定义此类型的数组(3)求哈夫曼编码,实质上是在已经建立的哈夫曼树中,从叶子结点开始,沿着结点的双亲链表域退回到根节点,每退回一步,就走过了哈夫曼树的一个分支,从而得到一位哈夫曼值,由于一个字符的哈夫曼编码是从根结点所经过的路径上各分支所组成的0、1序列,因此先得到的分支代码为所求编码的低位码,后得到的分支代码为所求编码的高位码,所以设计如下的数据类型:10;{[]; 每个结点的哈夫曼编码; 开始位置};(4)设置全局变量。
s; 为输入的字符串0; 记录输入的字符串中字母的种类,即叶子结点个数0; 记录字符串中字母的总个数[]叶子结点类型2、功能(函数)设计(1)统计字母种类和个数模块此模块的功能为从键盘接受一个字符串,统计字符串中字母种类即结点个数,每种字母出现次数即各叶子结点的权值。
哈夫曼编码课程设计

摘要哈夫曼编码是广泛用于数据文件压缩的十分有效的编码方法。
其压缩通常在20%~90%之间。
哈夫曼编码算法使用字符在文件中出现的频率表来建立一个用0,1串表示各字符的最优表示方式。
哈夫曼算法构造的扩充二叉树称为哈夫曼编码树或哈夫曼树。
当然,还有编码和译码部分。
本系统的前端开发工具是Visual C++6.0。
具有输入字符集大小及权值大小,构造哈夫曼树,并对用户输入的字符串进行编码以及译码还有退出四种功能。
本程序经过测试后,功能均能实现,运行稳定。
关键词:哈夫曼树,编码,译码,权值目录1问题描述 (1)2 问题分析 (2)3算法设计 (3)4算法实现 (4)5测试分析 (7)结论 (9)参考文献 (9)1 问题描述哈夫曼在上世纪五十年代初就提出这种编码时,根据字符出现的概率来构造平均长度最短的编码。
它是一种变长的编码。
哈夫曼编码应用广泛,如JPEG中就应用了哈夫曼编码。
在编码中,若各码字长度严格按照码字所对应符号出现概率的大小的逆序排列,则编码的平均长度是最小的。
构造好哈夫曼树后,就可根据哈夫曼树进行编码。
然而怎样构造一棵哈夫曼树呢?最具有一般规律的构造方法就是哈夫曼算法。
字符根据其出现的概率作为权值构造一棵哈夫曼树后,经哈夫曼编码得到的对应的码值。
只要使用同一棵哈夫曼树,就可把编码还原成原来那组字符。
显然哈夫曼编码是前缀编码,即任一个字符的编码都不是另一个字符的编码的前缀,否则,编码就不能进行翻译。
利用哈夫曼算法的编码和译码功能,重复地显示并处理以下项目,即构造哈夫曼树,编码及译码几项功能,直到选择退出为止。
本次设计就是为这样的一个哈夫曼的编/译码器。
哈夫曼编码所以能产生较短的码文,是因为哈夫曼树具有最小加权路径长度的二叉树。
如果叶结点的权值恰好是某个需编码的文本中各字符出现的次数,则编码后文本的长度就是该哈夫曼树的加权路径长度。
译码过程为自做向右逐一扫描码文,并从哈夫曼树的根开始,将扫到的二进制位串中的相邻位与哈夫曼树上标的0,1相匹配,以确定一条从根到叶子结点的路径,一旦到达叶子,则译出了一个字符。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
课程论文题目:哈夫曼树及其应用课程设计报告学号: 201230210115姓名:黄文宣班级: 1232101专业:信息安全课程名称:数据结构课程老师:王晓燕二零一肆年一月目录1、课程设计的题目及简介 (3)2、实验目的 (3)3、设计说明 (4)4、总体流图 (4)5、详细设计 (5)6、实现部分 (6)7、测试程序 (9)8、心得与体会 (10)一、课程设计题目哈夫曼树及其应用数据的读入﹑存储,生成文件,将键盘输入的信息存入指定的文件中;设计一程序求解此问题.哈夫曼(Huffman)编码原理是一种利用二叉树实现的编码原理建立的哈夫曼树编码,再从键盘输入二进制的编码进行译码,输出译码。
哈夫曼编码的码长是变化的,对于出现频率高的信息,编码的长度较短;而对于出现频率低的信息,编码长度较长。
这样,处理全部信息的总码长一定小于实际信息的符号长度。
锻炼我们的编码能力,真正理解数据结构的编码思想,并且锻炼我们的动手能力和成员间的配合,提高程序编写能力。
二、实验目的1 熟悉树的各种存储结构及其特点。
2 掌握建立哈夫曼树和哈夫曼编码的方法及带权路径长度的计算。
三、设计说明建立哈夫曼树,将哈夫曼树的结构定义为一个结构型的一维数组,每个元素含有四项:权值,双亲,左孩子,右孩子。
哈夫曼树上进行二进制编码:往左走,编码为0,往右走,编码为1,然后将从根结点到树叶中的所有0、1排列起来,则得到该树叶的哈夫曼编码。
哈夫曼编码用一个结构型的一维数组保存,每个元素包含:编码、编码的开始位置、编码所对应的字符三项。
给定的权值从键盘输入,输出所建立的哈夫曼树编码,再从键盘输入二进制的编码进行译码,输出译码。
四、总体流图哈夫曼树编码系统初始化编码重新建立哈夫曼树译码打印编码五、详细设计1.数据结构设计#include<iostream.h> //包含的库函数#include<string.h>#include<iomanip.h> const int n=6; //叶子数目const int m=2*n-1; //森林中树的棵树const int c=4;class tree { public: char data;int weight; //权值int parent; //双亲int lch,rch; //左右孩子void creathafumantree(); //建立哈夫曼树void editcode();//编码函数void trancode(char b[],int max);//译码函数哈夫曼树译码算法:译码:弹出译码界面→利用建立好的哈弗曼树进行译码→将译码输出→保存译码文件void tree::trancode(char b[],int max){ //译码int i=0;int j=m;cout<<"该段代码编译为:"<<endl;while(b[i]!='\0'){if(b[i]=='0')j=hftree[j].lch;elsej=hftree[j].rch;if(hftree[j].lch==0 && hftree[j].rch==0){cout<<hftree[j].weight;j=m;}i++;}}六、实现部分#include <string.h>#include <stdio.h>#include <stdlib.h>#define n 6#define m 2*n-1typedef struct{ float weight;int lchild,rchild,parent;}codenode;typedef codenode huffmantree[m];typedef struct{ char ch;char bits[n+1];}code;typedef code huffmancode[n];void inithf(huffmantree T) //-哈夫曼树的初始化{ int i;for(i=0;i<m;i++){ T[i].weight=0;T[i].parent=-1;T[i].lchild=-1;T[i].rchild=-1;}}void inputhf(huffmantree T) //-输入哈夫曼树的树据{ int i;float k;for(i=0;i<n;i++){ scanf("%f",&k);T[i].weight=k;}}void selectmin(huffmantree T,int k,int *p1,int *p2){ int i;float small1=10000,small2=10000;for(i=0;i<=k;i++){ if(T[i].parent==-1)if(T[i].weight<small1){ small2=small1;small1=T[i].weight;*p2=*p1;*p1=i;}elseif(T[i].weight<small2){ small2=T[i].weight;*p2=i;}}}void creathftree(huffmantree T) //-建哈夫曼树{ int i,p1,p2;inithf(T);inputhf(T);for(i=n;i<m;i++){ selectmin(T,i-1,&p1,&p2);T[p1].parent=T[p2].parent=i;T[i].lchild=p1;T[i].rchild=p2;T[i].weight=T[p1].weight+T[p2].weight;}}void creathfcode(huffmantree T, huffmancode H) //-哈夫曼编码表{ int i,c,p,start;char cd[n+1];cd[n]='\0';for(i=0;i<n;i++){ H[i].ch=getchar();start=n;c=i;while((p=T[c].parent)>=0){cd[--start]=(T[p].lchild==c)?'0':'1';c=p;}strcpy(H[i].bits,&cd[start]);}}void zip(huffmancode H,char *ch,char *s) //-编码{ int j=0;char *p[n]; unsigned int i;for(i=0;i<strlen(ch);i++){ while(ch[i]!=H[j].ch) j++;p[i]=H[j].bits;}strcpy(s,p[0]);for(i=1;i<n;i++)strcat(s,p[i]);puts(s);}void uzip(huffmancode H,char *s,huffmantree T) //-解码{ int j=0,p;unsigned int i;char ch[n+1];while(i<strlen(s)){ p=m-1;while(T[p].lchild!=-1){ if(s[ i]=='0'){ p=T[p].lchild;i++;}else{ p=T[p].rchild;i++;}}ch[j]=H[p].ch;j++;}ch[j]='\0';puts(ch);}main(){ char ch[]="abcdef", s[36];huffmantree T;huffmancode H;creathftree(T);creathfcode(T,H);zip(H,ch,s);uzip(H,s,T);}七、测试程序七、心得体会这次实验,感觉到相对难度较大,用了比较长的时间来做,从这也反映了对树的知识不够熟练。
但在这次实验的练习中,不仅对树的知识进行了综合运用,还有了较深一步的了解,掌握了运用树的基本知识。
总之,对树和二叉树这方面的知识了解和运用都还有待加强。
在实验中也出现了很多的问题,最大的问题就是对程序设计框架结构的不了解,在实现代码与功能的连接时经常会出现各种不同的错误,在实现一些功能时系统常常会报错。
许多错误不知从哪修改,让程序运行不出来。
课程设计中,既回顾了很多以前的东西,也发现了很多的问题,以前都没遇见过的,收获很大。
通过本次数据结构的课程设计,我学习了很多在上课没懂的知识,并对求哈夫曼树及哈夫曼编码/译码的算法有了更加深刻的了解,更巩固了课堂中学习有关于哈夫曼编码的知识,此次哈夫曼树的应用系统的设计让自己对数据结构的了解更深入。
通过老师和同学的细心的帮助,终于做出了这个系统,感觉很棒!。