1、HuffMan课程设计报告课程设计综合成绩评定设计题目: 哈夫曼编/译码器 考核项目分值AC得分设计态度(共10分)10按要求出勤,设计态度认真、积极设计态度比较认真设计情况(共30分)设计工作量与难度10设计工作量达到要求、设计有一定难度设计工作量与难度一般,基本达到了要求设计方案5设计方案正确、合理设计方案较正确、基本合理,但不是最优设计完成情况15能够按照面向对象的思想完成了选题的设计内容,界面设计合理,相关算法设计正确,程序结果正确、直观性好基本完成了选题的设计内容及主要选题功能,相关算法设计基本正确,程序结果正确设计报告(共30分)报告组织结构及内容15内容组织及结构合理、内容充实、
2、层次清晰、图表得当内容组织及结构较合理、内容较充实、层次较清晰、图表应用基本得当报告排版格式15格式规范,完全符合要求格式基本规范,基本符合要求答辩情况(共30分)30答辩思路清晰,问题回答准确问题基本回答准确综合得分其它说明:目 录一、问题描述 1二、概要设计 22.1界面设计 22.2算法设计 3三、详细设计 4四、程序运行说明与结果 9五、总结与分析 13一、问题描述电文编码:假如有一份电文中有若干个字符,以每个字符出现的频度作为叶子结点的权值创建对应的哈夫曼树(权值最小的作为左子树,次小的作为右子树),并输出每个字符对应的哈夫曼编码。1. 程序的输入(1)若干字符(代表电文)2. 程序
3、的输出(1)每个字符对应的哈夫曼编码(2)每个字符对应的权值(3)电文经过编码后的二进制代码电文译码:给出一段二进制代码的电文,要求根据前面构造的哈夫曼树进行译码。在前面编码的基础上,键盘输入一段电文,则能在屏幕上显示出自动翻译好的电文。1. 程序的输入(1) 由0和1组成的二进制代码(代表电文)2. 程序的输出(1)每个字符对应的哈夫曼编码(2)每个字符对应的权值(3)电文经过译码后的译码结果二、概要设计2.1界面设计图1 哈夫曼编/译码器界面哈夫曼编/译码器分为显示区域、输入区域和按钮区域三个部分。显示区域分别显示字符编码、字符权值和编码结果。输入区域输入若干字符(电文)。按钮区域包括自动
4、获取权值、保存字符权值、打开编码文件、保存编码内容、保存编码结果和开始编码按钮。对应控件属性如表1所示。表 1 主界面控件属性控件(Name)属 性属 性 新 值richTextBoxScanText输入编/译码内容richTextBoxPrintText输出编/译码结果richTextBoxPrintCodeText输出字符编码richTextBoxSetWeightText输出字符权值labelScanText请输入要编/译码的内容:labelPrintText编/译码结果为:续表控件(Name)属 性属 性 新 值labelPrintCodeText字符编码为:labelPrintWei
5、ghtText字符权值为:buttonSetWeightText自动获取权值buttonSaveWeightText保存字符权值buttonOpenText打开编/译码文件buttonSaveTextText保存编/译码内容buttonSaveText保存编/译码结果buttonTraText开始编/译码checkBoxEnCodeText编码checkBoxDeCodeText译码2.2算法设计在此程序算法设计中,核心算法为哈夫曼树的构造算法与哈夫曼编码算法。在哈夫曼树的构造算法中,需要定义哈夫曼树的存储类型,需要根据结点数量以及权值构建哈夫曼树。在哈夫曼编码算法中,需从每个叶子结点访问至根
6、节点,并记录访问路径(0或1)。1. LeafNode类中定义了叶子结点的权值(weight),双亲结点(parent),左孩子结点(lChild),右孩子结点(rChild),以及叶子结点的名字(nameStr)。此类中还有一个无参构造方法(LeafNode()),用于对叶子结点进行初始化操作。2. CreateHuffmananTree类含无参构造器(CreateHuffmananTree()),用以对所有叶子结点进行初始化操作。类中还包含一个方法(Creat()),可以根据所有叶子结点的权值构造哈夫曼树。3. GetHuffmanCode类中有GetHuffCode(),GetNameS
7、tr()两个方法。GetHuffCode()用来获取哈夫曼编码,GetNameStr()用于实现将二进制代码解译为字符(电文)。4. EnCodeAndDeCode类中两个方法,GetCode()方法和DeCode()方法。GedCode()方法中创建CreateHuffmanTree类的对象,实现创建哈夫曼树,并对字符进行编码。DeCode()方法中创建CreateHuffmanTree类的对象,实现创建哈夫曼树,并解译二进制代码。三、详细设计1. LeafNode类(定义叶子结点类型)public class LeafNode public int weight;/用来存储叶子结点的权值
8、public int lChild;/存储左孩子的数组编号 public int rChild;/用来存储右孩子的数组编号 public int parents;/用来存储双亲的数组编号 public string nameStr;/用来存储叶子结点的信息 /无参构造器 public LeafNode() weight = -1; lChild = -1; rChild = -1; parents = -1; nameStr = null; 2. CreateHuffmanTree类(构建哈夫曼树算法) public class CreateHuffmanTree public static
9、LeafNode leaf;/结点以数组形式存放 public static int leafNum;/叶子结点数目 /构造器 public CreateHuffmanTree() StreamReader reader = new StreamReader(SetWeight.txt, Encoding.Default);/读取文件流 for (leafNum = 0; !reader.EndOfStream;) if (reader.ReadLine().Trim() != )leafNum+; reader.Close(); leaf = new LeafNode2 * leafNum
10、- 1; for (int i = 0; i 2 * leafNum - 1; i+) leafi = new LeafNode();/初始化全部叶结点 /创建huffmantree,用creat()方法 public void Creat() int tmp1;/用来存放未加入树的结点的权值 int tmp2;/判定tmp1是否已经被赋值 int min1; int min2;/用来存放权值最小的两个结点 /输入n个叶子结点的权值和储存的信息 string str; StreamReader reader = new StreamReader(SetWeight.txt);/读取文件流 fo
11、r (int i = 0; i leafNum; i+) str = reader.ReadLine().Split(=);/以“=”为标志将一行字符串分割成左右两部分字符串,如果不是这个格式的信息将会抛出异常,被catch捕获 leafi.weight = int.Parse(str1);/“=”右边的部分转成整形收入到叶子结点的权值 leafi.nameStr = str0;/=左边的部分依然保持string类型作为叶子结点的信息存储 reader.Close();/关闭读入流 for (int i = 0; i leafNum - 1; i+)/处理n个叶子结点,建立哈夫曼树 tmp1
12、= tmp2 = int.MaxValue; min1 = min2 = 0;/在全部结点中找权值最小的两个结点 for (int j = 0; j leafNum + i; j+) if (leafj.parents = -1) if (leafj.weight tmp2) tmp2 = leafj.weight; min2 = j; if (tmp2 tmp1) int swap = tmp2; tmp2 = tmp1; tmp1 = swap; swap = min2; min2 = min1; min1 = swap; leafmin1.parents = leafNum + i; l
13、eafleafNum + i.weight = leafmin1.weight + leafmin2.weight; leafleafNum + i.lChild = min1; leafleafNum + i.rChild = min2; leafmin2.parents = leafNum + i; 3. GetHuffmanCode类(获取哈夫曼编码)public class GetHuffmanCode public static string code;/code用来存储编码 public static int codeTmp;/这个用来存储0/1临时编码的 public stati
14、c string PrintCode; public static int i, j; public static void GetHuffCode(string toBeTran)/获取哈夫曼编码 Stack codeStack = new Stack();/利用栈的先进后出反转代码 for (i = 0; i CreateHuffmanTree.leafNum; i+) if (toBeTran = CreateHuffmanTree.leafi.nameStr)/如果传入的字符和叶子结点的字符信息相同,回溯法找代码 j = CreateHuffmanTree.leafi.parents;
15、 break; if (i = CreateHuffmanTree.leafNum) GetHuffmanCode.code = toBeTran; if (j = -1) /只存在一个叶子结点 codeTmp = 0; codeStack.Push(codeTmp.ToString(); while (j != -1) /直到根节点(parent属性为-1)时跳出循环 if (CreateHuffmanTree.leafj.lChild = i) codeTmp = 0; else if (CreateHuffmanTree.leafj.rChild = i) codeTmp = 1;/左0
16、右1 codeStack.Push(codeTmp.ToString(); i = j; j = CreateHuffmanTree.leafi.parents; /代码全部入栈 while (codeStack.Count != 0)/代码全部弹出栈,实现反序 code += codeStack.Pop(); public static void GetNameStr(int nameCode) /解译哈夫曼编码 /根节点一定是leaf2*leafNum-2,即最后一个数组 if (nameCode = 0) i = CreateHuffmanTree.leafi.lChild; if (C
17、reateHuffmanTree.leafi.lChild = -1) code += CreateHuffmanTree.leafi.nameStr; i = 2 * CreateHuffmanTree.leafNum - 2; else if (nameCode = 1) i = CreateHuffmanTree.leafi.rChild; if (CreateHuffmanTree.leafi.lChild = -1) code += CreateHuffmanTree.leafi.nameStr; i = 2 * CreateHuffmanTree.leafNum - 2; 4. E
18、nCodeAndDeCode类(编/译字符)public class EnCodeAndDeCode public static string codeFile;/最终用来存放代码串的 /public static string codeFile2; public static void GetCode() CreateHuffmanTree huff = new CreateHuffmanTree(); huff.Creat(); char toBeTranText = HuffManTra.CodeInfo.ToCharArray(); try/在这里抛出异常是为了防止大面积出现编码错误是
19、反复弹出出错提示窗口,这里只弹出第一个出错信息提示 for (int i = 0; i HuffManTra.CodeInfo.Length; i+) GetHuffmanCode.GetHuffCode(toBeTranTexti.ToString(); codeFile += GetHuffmanCode.code; GetHuffmanCode.code = null; catch (IndexOutOfRangeException) codeFile = null; GetHuffmanCode.code = null; public static void DeCode() Crea
20、teHuffmanTree huff = new CreateHuffmanTree(); huff.Creat(); GetHuffmanCode.i = 2 * CreateHuffmanTree.leafNum - 2; char tmpChar; tmpChar = HuffManTra.CodeInfo.ToCharArray(); for (int i = 0; i tmpChar.Length; i+) GetHuffmanCode.GetNameStr(tmpChari - 48); codeFile = GetHuffmanCode.code; GetHuffmanCode.
21、code = null; 四、程序运行说明与结果运行程序,首先进入主界面(如上文图1所示)。若进行电文编码,首先选中“编码”,然后在“请输入要编码的内容”下的richTextBox控件内输入内容(如图2所示),或者点击“打开编码文件”按钮,选择txt文件。图2 输入编码内容点击“自动获取权值”按钮,获取字符编码与字符权值(如图3所示)。图3 自动获取权值点击“开始编码”按钮,显示编译结果(如图4所示)。图4 编译结果此时,电文编码成功。可以点击“保存字符权值”按钮,保存字符权值信息,可以点击“保存编码内容”按钮,保存编码内容,也可以点击“保存编码结果”按钮,保存编码结果。若要进行电文译码,首先
22、选中“译码”,并输入二进制代码(如图5所示),或者点击“打开译码文件”按钮,打开txt文件。图5 输入译码内容点击“自动获取权值”按钮,弹出“设置权值”窗体(如图6所示)。图6 设置权值此时,窗体中显示的是上一次进行编码时的权值信息。若使用此权值,则直接退出即可。若不使用此权值,可打开“文件”菜单中的“打开文件”选项,选择其它权值txt文件,并点击“文件”菜单中的“保存”按钮,退出即可。这里我们选择直接退出,然后就会显示出字符编码与字符权值信息。图7 显示字符编码与权值点击“开始译码”按钮,显示编译结果(如图8所示)。图8 译码结果五、总结与分析本程序是由C#编写的标准Windows窗体应用程序,是结合数据结构与Windows窗体的综合设计。数据结构设计中包含哈夫曼树的建立,以及对哈夫曼树中每个叶子结点的遍历,并用静态链表实现哈夫曼树的存储。在获取字符(电文)对应的编码时,利用栈的后进先出(FIFO)特性,将得到的编码反序后输出。本程序中包含对字符(电文)的编码和对二进制串的译码,同时可显示编译时的字符权值、字符编码、编译结果。本程序存在一些不足,将不能对中文字符或某些特殊字符进行编码。编译时会出现错误提示,提醒使用者进行修改输入内容,以便于正确编译。
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1