1、#include#include#include#define MAX 99char chaMAX;char hcMAX-1MAX;int s1,s2; /设置全局变量,以便在方法(函数)select中返回两个变量typedef struct /huffman树存储结构unsigned int weight;/权值int lchild,rchild,parent;huftree;void select(huftree tree,int k) /找寻parent为0,权最小的两个节点int i;for (i=1;i“;cinanychar;cout“;cinb;coutin;coutn; cou
2、t“;cinchaiweighti;huffman(tree,w,n); break; /生成huffman树case 2:huffmancode(tree,code,n);break;case 3:tohuffmancode(n);break;case 4:decode(cha,tree,n);break;一、设计题目与要求【问题描述】设计一个利用哈夫曼算法的编码和译码系统,重复地显示并处理以下项目,直到选择退出为止。【内容】1) 初始化:键盘输入字符集大小 n、n 个字符和 n 个权值,建立哈夫曼树;2) 编码:利用建好的哈夫曼树生成哈夫曼编码;3) 输出编码;4) 译码功能5) 显示哈夫
3、曼树;6)二、概要设计这个设计主要是解决如何将字符进行哈夫曼编和译码的功能,主要分为头节点、select 程序、创建哈夫曼树、输出哈夫曼树、输出哈夫曼编码和译码功能。创建 Huffman 树原理:假设有 n 个权值,则构造出的哈夫曼树有 n 个叶子结点。 n 个权值分别设为 w1、w2、,然后将其认为有 n 棵树的森林,在森林中选出两个根结点的权值最小的树合并,作为一棵新树的左、右子树且新树的根结点权值为其左、右子树根结点权值之和,从森林中删除选取的两棵树,并将新树加入森林,一直重复这个过程,最后合成唯一的一个树即为 Huffman 树;首先要对数进行定义。然后进行初始化,将每个节点的所有指针
4、都标记为-1,m 个叶结点的哈夫曼树共有 2m-1 个结点,然后构造哈夫曼树的 m-1 个非叶结点,然后查找文件中权值最小的两个结点相结合,用 for 循环实现最小权值结合,最后构成哈夫曼树。1. select 程序是为了寻找最小权值的字符,不断地循环找寻最小权值。2. 创建哈夫曼树是将最小的权值依次相结合成成一个大的二叉树3. 输出哈夫曼树是将二叉树用矩阵的方式表达出来4. 输出哈夫曼编码是将输入的字符用 01 串的形式表达出来5. 译码功能是将 01 串的哈夫曼编码在二叉树中的字符输出译码退出开始建立哈夫曼树 输出哈夫曼编码编码三、算法设计1、 生成huffman树(流程图如下1.1)图1
5、.1这是生成哈夫曼树的流程图,节点一共有2n-1个,首先给n个叶子赋值,初始化其余的n-1个节点,然后寻找双亲,再给双亲赋值。在给n个叶子赋值时要先挑选出两棵根节点最小的树最为左右子树构造。新的树的权值是这两个树的权值之和。在生成哈夫曼树之前还有一个寻找最小权值的select函数,这个函数是生成哈夫曼树的一个重要的函数,流程图如下图2.哈夫曼编码的输出(如图)哈夫曼编码的输出是将n-1的节点赋给start,然后经i赋给c,i的双亲则赋值给f,在进行循环的时候,f与c的关系则是f一直都是c的双亲,当f=0的时候则此时的c就是二叉树的根节点,如果左孩子等于c则记为0,如果有孩子是C则记为1,然后根
6、据左零右一的定则依次读取,因为程序的读取是从树的最下端的叶子依次往上读取,所以要反转存储的顺序,将先前的01串从后往前进行读取储存 3.译码译码是根据哈夫曼编码来读取字符,相对于哈夫曼编码的输出是一个反向的过程,首先输入01字符串,然后根据字符串的01的顺序来读取哈夫曼树中的字符。首先输入编码,当编码不为空的时候,如果输入的编码是零则是左孩子,1则是右孩子,如此类推,最后寻找到字符的所在地位置,然后输出字符。如果排定左孩子不等于零,则说明输入的编码错误。四、运行结果和调试分析1.建立和初始化哈夫曼树在初始化的过程是在寻找最小权值的时候进行的,然后把最小的两个权值分别赋给s1和s2,在这段程序中的对字符与权值的输入上遇到了一些麻烦,运用了c+中输入与输出。2.输出哈弗曼编码在输出哈夫曼编树的时候因为存在C+的内容在看哈夫曼树的时候没有看懂矩阵所表达的意思,在老师的帮助和分析下才理解了,这个输出矩阵的每一列所表达的含义3.输出哈夫曼编码4译码在译码的环节也出现了问题,并且没有解决,就是当输入编码的时候,例如c的编码为011,但是当输入的编码是0111时的时候也会输出的字符的C,这个问题一直没有得到解决。