北邮数据结构实验—Huffman编码解码器.docx
数据结构实验实验报告Huffman赫夫曼编码及应用

实验报告课程名称:数据结构实验名称:赫夫曼编码及应用院(系):计算机与通信工程学院专业班级:计算机科学与技术姓名:学号:指导教师:2020 年 5 月12 日一、实验目的掌握赫夫曼树和赫夫曼编码的基本思想和算法的程序实现。
二、实验内容及要求1、任务描述a.提取原始文件中的数据(包括中文、英文或其他字符),根据数据出现的频率为权重,b.构建Huffman编码表;c.根据Huffman编码表对原始文件进行加密,得到加密文件并保存到硬盘上;d.将加密文件进行解密,得到解码文件并保存点硬盘上;e.比对原始文件和解码文件的一致性,得出是否一致的结论。
2、主要数据类型与变量a.对Huffman树采用双亲孩子表示法,便于在加密与解密时的操作。
typedef struct Huffman* HuffmanTree;struct Huffman{unsigned int weight; //权值unsigned int p, l, r;//双亲,左右孩子};b.对文本中出现的所有字符用链表进行存储。
typedef struct statistics* List;struct statistics {char str; //存储此字符int Frequency; //出现的频率(次数)string FinalNum; //Huffman编码struct statistics* Next;};3、算法或程序模块对读取到的文本进行逐字符遍历,统计每个字符出现的次数,并记录在创建的链表中。
借助Huffman树结构,生成结构数组,先存储在文本中出现的所有字符以及它们出现的频率(即权值),当作树的叶子节点。
再根据叶子节点生成它们的双亲节点,同样存入Huffman树中。
在完成对Huffman树的创建与存储之后,根据树节点的双亲节点域以及孩子节点域,生成每个字符的Huffman编码,并存入该字符所在链表节点的FinalNum域。
北邮信通院数据结构实验报告三哈夫曼编码器.pptx

-1
2.2 关键算法分析 (1)计算出现字符的权值
利用 ASCII 码统计出现字符的次数,再将未出现的字符进行筛选,将出现的字符及頻 数存储在数组 a[]中。
void Huffman::Init() {
int nNum[256]= {0}; //记录每一个字符出现的次数 int ch = cin.get();
第2页
北京邮电大学信息与通信工程学 院
2
-1
-1
-1
5
-1
-1
-1
6
-1
-1
-1
7
-1
-1
-1
9
-1
-1
-1
weight lchild rchild parent
2
-1
-1
5
5
-1
-1
5
6
-1
-1
6
7
-1
-1
6
9
-1
-1
7
7
0
1
7
第3页
北京邮电大学信息与通信工程学 院
13
2
3
8
16
5
4
8
29
6
7
2、建立编码表(CreateTable):利用已经建好的赫夫曼树进行编码,并将每 个字符的编码输出。
3、编码(Encoding):根据编码表对输入的字符串进行编码,并将编码后的 字符串输出。
4、译码(Decoding):利用已经建好的赫夫曼树对编码后的字符串进行译 码,并输出译码结果。
5、打印(Print):以直观的方式打印赫夫曼树(选作) 6、计算输入的字符串编码前和编码后的长度,并进行分析,讨论赫夫
北邮数据结构实验—Huffman编码解码器

数据结构实验报告实验名称:____Huffman编码/解码器_____学生姓名:__________________班级:__________________班内序号:__________________学号:__________________日期:___________________1.实验要求利用二叉树结构实现哈夫曼编/解码器。
基本要求:1.初始化(Init):能够对输入的任意长度的字符串s进行统计,统计每个字符的频度,并建立哈夫曼树2.建立编码表(CreateTable):利用已经建好的哈夫曼树进行编码,并将每个字符的编码输出。
3.编码(Encoding):根据编码表对输入的字符串进行编码,并将编码后的字符串输出。
4.译码(Decoding):利用已经建好的哈夫曼树对编码后的字符串进行译码,并输出译码结果。
5.计算输入的字符串编码前和编码后的长度,并进行分析,讨论赫夫曼编码的压缩效果。
2. 程序分析存储结构静态三叉链表程序流程 (或程序结构、或类关系图等表明程序构成的内容,一般为流程图等)流程图伪代码1.输入进行编码的字符串2.遍历字符串,并为叶子节点权重赋值3.依次对各字符进行哈弗曼编码,自下往上,若是双亲节点左孩子则编码前插入‘0’,若是双亲节点右孩子则编码钱插入‘1’。
4.显示各字符的哈弗曼编码。
5.对字符串进行编码,挨个遍历字符,找到相应的编码,复制到总的编码里,最后输出字符串的编码。
6.对字符串的哈弗曼码进行译码。
自上往下,若是‘0’,则递归到左孩子,若是‘1’,则递归到右孩子,知道叶子节点,输出该叶子节点代表字符,再继续遍历。
7.分析内存占用情况。
若用ASCII编码,每个字符占1个字节,即8bit,该情况下占用内存就是(字符长度)*8。
若用哈弗曼编码,占用内存是各(字符频度)*(每个字符占用位数)之和。
关键算法分析该程序关键算法即哈弗曼编码,语句如下:void CHTree::huffmancode(){int i;if(n<=1)return;m=2*n-1;for(i=1;i<=n;i++)arent=0;ht[i].lchild=0;ht[i].rchild=0;}for(;i<=m;i++) eight=0;ht[i].parent=0;ht[i].lchild=0;ht[i].rchild=0;}for(i=n+1;i<=m;++i)arent设为-1s2=select(i-1);ht[s1].parent=i;ht[s2].parent=i;ht[i].lchild=s1;ht[i].rchild=s2;ht[i].weight=ht[s1].weight+ht[s2].weight;}int c,f;for(i=1;i<=n;++i) {for(c=i,f=ht[i].parent;f!=0;c=f,f=ht[f].parent)child==c){str[i].insert(0,"0",0,1);} nsert(0,"1",0,1);} 序运行结果分析首先,要求用户输入进行编码的字符串,遍历字符串,并为叶子节点权重赋值。
北邮数据结构实验报告

北邮数据结构实验报告北京邮电大学信息与通信工程学院2009级数据结构实验报告实验名称:实验三哈夫曼编/解码器的实现学生姓名:陈聪捷日期:2010年11月28日1.实验要求一、实验目的:了解哈夫曼树的思想和相关概念;二、实验内容:利用二叉树结构实现哈夫曼编/解码器1.初始化:能够对输入的任意长度的字符串s进行统计,统计每个字符的频度,并建立哈夫曼树。
2.建立编码表:利用已经建好的哈夫曼树进行编码,并将每个字符的编码输出。
3.编码:根据编码表对输入的字符串进行编码,并将编码后的字符串输出。
4.译码:利用已经建好的哈夫曼树对编码后的字符串进行译码,并输出译码结果。
5.打印:以直观的方式打印哈夫曼树。
6.计算输入的字符串编码前和编码后的长度,并进行分析,讨论哈夫曼编码的压缩效果。
7.用户界面可以设计成“菜单”方式,能进行交互,根据输入的字符串中每个字符出现的次数统计频度,对没有出现的字符一律不用编码。
2.程序分析2.1存储结构二叉树templateclassBiTree{public:BiTree();//构造函数,其前序序列由键盘输入~BiTree(void);//析构函数BiNode*Getroot();//获得指向根结点的指针protected:BiNode*root;//指向根结点的头指针};//声明类BiTree及定义结构BiNodeData:二叉树是由一个根结点和两棵互不相交的左右子树构成data:HCode*HCodeTable;//编码表inttSize;//编码表中的总字符数二叉树的节点结构templatestructBiNode//二叉树的结点结构{Tdata;//记录数据Tlchild;//左孩子Trchild;//右孩子Tparent;//双亲};编码表的节点结构structHCode{chardata;//编码表中的字符charcode[100];//该字符对应的编码};待编码字符串由键盘输入,输入时用链表存储,链表节点为structNode{charcharacter;//输入的字符unsignedintcount;//该字符的权值boolused;//建立树的时候该字符是否使用过Node*next;//保存下一个节点的地址};示意图:2.2关键算法分析1.初始化函数(voidHuffmanTree::Init(stringInput))算法伪代码:1.初始化链表的头结点2.获得输入字符串的第一个字符,并将其插入到链表尾部,n=1(n 记录的是链表中字符的个数)3.从字符串第2个字符开始,逐个取出字符串中的字符3.1将当前取出的字符与链表中已经存在的字符逐个比较,如果当前取出的字符与链表中已经存在的某个字符相同,则链表中该字符的权值加1。
Huffman编解码实验报告

Huffman编解码实验报告⽂本⽂件的⼆进制预统计Huffman编解码⼀、实验⽬的(1) 熟悉Huffman编解码算法;(2) 理解Huffman编码的最佳性。
⼆、实验内容1、编程思想霍夫曼(Huffman)编码是1952年为⽂本⽂件⽽建⽴,是⼀种统计编码。
属于⽆损压缩编码。
霍夫曼编码的码长是变化的,对于出现频率⾼的信息,编码的长度较短;⽽对于出现频率低的信息,编码长度较长。
这样,处理全部信息的总码长⼀定⼩于实际信息的符号长度。
计算机编程实现时,⾸先统计带编码的⽂本⽂件中各个字符出现的概率,然后将概率作为节点的权值构建huffman树。
编码时从叶⼦节点出发,如果这个节点在左⼦树上,则编码0,否则编码1,直到根节点为⽌,所得到的01序列即为该叶⼦节点的编码。
所有叶⼦节点的编码构成⼀个码本。
有两种译码⽅法:(1)按位读⼊码字,从已建好的Huffman树的根节点开始,若码字为“0”,则跳到左⼦树,若为“1”则跳到右⼦树,直到叶⼦结点为⽌,输出叶⼦接点所表⽰的符号。
(2)由于Huffman编码是唯⼀码,还有另⼀种译码⽅法,每读⼊⼀位编码就去码本中去匹配相应的码字,若匹配不成功,则继续读⼊下⼀个编码,直到匹配成功为⽌。
显然前⼀种⽅法⽐较简便,本程序采⽤便是该⽅法。
2、程序流程图3、编程实现本实验采⽤⽤C 语⾔程序语⾔,VC++ 6.0编程环境。
(1)数据结构构造存放符号及其权值的存储结构如下 typedef struct {unsigned char symbol; //符号的ASCII 码值 int sweight; //权值}syml_weit;syml_weit *sw;构造huffman 树存储结构如下:typedef struct {int weit; //权值int lchd; //左孩⼦地址 int rchd; //右孩⼦地址 int part; //双亲地址 }hufmtree;hufmtree *htree;(2)函数本程序共包含5个函数:⼀个主函数:void main(), 4个⼦函数:void CountWeight(unsigned char *DataBuf,int FileLen); void BuildTree();void HufmCode(unsigned char *DataBuf,int FileLen); void HufmDCode(unsigned char *CDataBuf,int CDataLen); 其功能分别CountWeight----计算⽂本⽂件中各符号的权值; BuildTree-------构建Huffman 树,形成码本; HufmCode---------对⽂本⽂件进⾏编码; HufmDCode-------进⾏译码。
北邮信通院数据结构实验报告三哈夫曼编码器.docx

北京邮电大学电信工程学院数据结构实验报告实验名称:实验三树——哈夫曼编/解码器学生姓名:班级:班内序号:学号:日期: 2014 年 12 月 11 日1.实验要求利用二叉树结构实现赫夫曼编/解码器。
基本要求:1、初始化 (Init) :能够对输入的任意长度的字符串s 进行统计,统计每个字符的频度,并建立赫夫曼树2、建立编码表 (CreateTable):利用已经建好的赫夫曼树进行编码,并将每个字符的编码输出。
3、编码 (Encoding):根据编码表对输入的字符串进行编码,并将编码后的字符串输出。
4、译码 (Decoding):利用已经建好的赫夫曼树对编码后的字符串进行译码,并输出译码结果。
5、打印 (Print):以直观的方式打印赫夫曼树(选作)6、计算输入的字符串编码前和编码后的长度,并进行分析,讨论赫夫曼编码的压缩效果。
测试数据:I love data Structure, I love Computer。
I will try my best to study data Structure.提示:1、用户界面可以设计为“菜单”方式:能够进行交互。
2、根据输入的字符串中每个字符出现的次数统计频度,对没有出现的字符一律不用编码。
-2.程序分析2.1 存储结构Huffman 树给定一组具有确定权值的叶子结点,可以构造出不同的二叉树,其中带权路径长度最小的二叉树称为Huffman树,也叫做最优二叉树。
weight lchild rchild parent2-1-1-15-1-1-16-1-1-17-1-1-19-1-1-1weight lchild rchild parent 2-1-15 5-1-15 6-1-16 7-1-16 9-1-17 701713238165482967-12.2 关键算法分析(1)计算出现字符的权值利用 ASCII 码统计出现字符的次数,再将未出现的字符进行筛选,将出现的字符及頻数存储在数组a[] 中。
huffman编码及截断huffman编码、解码实习报告(pdf版)

下面先介绍下 tree,树在 matlab 中的构造,在 matlab 中用 tree(MN,s1,s2,s3……) 这个系统函数来构造二叉树。声明一个 tree(6,x)结构的树型结点,一个结点包括有 6 个变 量存储单元。 其中 tree(1,x)记录该结点的编号; tree(2,x)记录该结点的概率值; tree(3,x) 记录该结点的父结点编号; tree(4,x)记录该结点是左结点还是右结点(其中左结点为 “0” , 右结点为“1”);tree(5,x)记录该结点是否为根结点标志(该结点为根结点记为“1”,否 则决为“0”)。tree(6,x)记录该结点的字符,x 的个数为 pro 中字符的个数,其余值人为 赋零。 由截断 Huffman 编码要求(2),我们需要对字符进行一个定长码的顺序编码,所以需 要编写函数 SequenceTree=Sequence(pro)来得到一棵顺序编码的二叉树,其中 pro 为截断 Huffman 编码要求中剩余的字符组成的新 pro 概率分布矩阵 (按概率值先大后小的顺序排序)
Entropy=0; for j=1:n1; Entropy=Entropy-pro(1,j)*log2(pro(1,j)); End
计算平均码长前需要先得到每个字符的码长, 因此需要先编写得到每个字符码长的数组 (代码略,详见第四部分:编程代码),接着由下得到平均码长
AverageCodeLength=sum(CodeLength.*pro(1,:)) 再根据冗余度的计算公式可得 Redundancy= AverageCodeLength/ Entropy-1;
北邮-数据结构-哈夫曼树报告Word版

数据结构实验报告实验名称:哈夫曼树学生姓名:袁普班级:2013211125班班内序号:14号学号:2013210681日期:2014年12月实验目的和内容利用二叉树结构实现哈夫曼编/解码器。
基本要求:1、初始化(Init):能够对输入的任意长度的字符串 s进行统计,统计每个字符的频度,并建立哈夫曼树2、建立编码表(CreateTable):利用已经建好的哈夫曼树进行编码,并将每个字符的编码输出。
3、编码(Encoding):根据编码表对输入的字符串进行编码,并将编码后的字符串输出。
4、译码(Decoding):利用已经建好的哈夫曼树对编码后的字符串进行译码,并输出译码结果。
5、打印(Print):以直观的方式打印哈夫曼树(选作)6、计算输入的字符串编码前和编码后的长度,并进行分析,讨论赫夫曼编码的压缩效果。
7、可采用二进制编码方式(选作)测试数据:I love data Structure, I love Computer。
I will try my best to studydata Structure.提示:1、用户界面可以设计为“菜单”方式:能够进行交互。
2、根据输入的字符串中每个字符出现的次数统计频度,对没有出现的字符一律不用编码2. 程序分析2.1 存储结构用struct结构类型来实现存储树的结点类型struct HNode{int weight; //权值int parent; //父节点int lchild; //左孩子int rchild; //右孩子};struct HCode //实现编码的结构类型{char data; //被编码的字符char code[100]; //字符对应的哈夫曼编码};2.2 程序流程2.3 关键算法分析算法1:void Huffman::Count()[1] 算法功能:对出现字符的和出现字符的统计,构建权值结点,初始化编码表[2] 算法基本思想:对输入字符一个一个的统计,并统计出现次数,构建权值数组,[3] 算法空间、时间复杂度分析:空间复杂度O(1),要遍历一遍字符串,时间复杂度O(n)[4] 代码逻辑:leaf=0; //初始化叶子节点个数int i,j=0;int s[128]={0}; 用于存储出现的字符for(i=0;str[i]!='\0';i++) 遍历输入的字符串s[(int)str[i]]++; 统计每个字符出现次数for(i=0;i<128;i++)if(s[i]!=0){data[j]=(char)i; 给编码表的字符赋值weight[j]=s[i]; 构建权值数组j++;}leaf=j; //叶子节点个数即字符个数for(i=0;i<leaf;i++)cout<<data[i]<<"的权值为:"<<weight[i]<<endl;算法2:void Init();[1] 算法功能:构建哈弗曼树[2] 算法基本思想:根据哈夫曼树构建要求,选取权值最小的两个结点结合,新结点加入数组,再继续选取最小的两个结点继续构建。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
北京邮电大学电信工程学院数据结构实验报告实验名称: ____Huffman 编码 /解码器 _____学生姓名: __________________班级: __________________班内序号: __________________学号: __________________日期: ___________________-1.实验要求利用二叉树结构实现哈夫曼编/ 解码器。
基本要求:1.初始化 (Init) :能够对输入的任意长度的字符串s 进行统计,统计每个字符的频度,并建立哈夫曼树2.建立编码表 (CreateTable):利用已经建好的哈夫曼树进行编码,并将每个字符的编码输出。
3.编码 (Encoding) :根据编码表对输入的字符串进行编码,并将编码后的字符串输出。
4.译码 (Decoding) :利用已经建好的哈夫曼树对编码后的字符串进行译码,并输出译码结果。
5.计算输入的字符串编码前和编码后的长度,并进行分析,讨论赫夫曼编码的压缩效果。
2. 程序分析2.1 存储结构静态三叉链表Weight Lchild Rchild parent2.2 程序流程(或程序结构、或类关系图等表明程序构成的内容,一般为流程图等 )2.2.1.流程图开始输入进行编码的字符串统计各个字符的频度,并对各叶子节点的权重赋值初始化各节点的Lchild , Rchild 和 parent进行哈弗曼编码是否最后一个字符是输出各字符编码对字符串进行编码找到当前字符编码,复制到总编码中是否最后一个字符是输出各字符串编码对哈弗曼码进行译码输出译码结果是否判断双亲节点否-该节点是否为根节点否若为左孩子若为右孩子编码前插入0编码前插入1-输出占用情况结束2.2.1.伪代码1.输入进行编码的字符串2.遍历字符串,并为叶子节点权重赋值3.依次对各字符进行哈弗曼编码,自下往上,若是双亲节点左孩子则编码前插入‘0’,若是双亲节点右孩子则编码钱插入‘1’。
4.显示各字符的哈弗曼编码。
5.对字符串进行编码,挨个遍历字符,找到相应的编码,复制到总的编码里,最后输出字符串的编码。
6.对字符串的哈弗曼码进行译码。
自上往下,若是‘0’,则递归到左孩子,若是‘1’,则递归到右孩子,知道叶子节点,输出该叶子节点代表字符,再继续遍历。
7.分析内存占用情况。
若用ASCII 编码,每个字符占 1 个字节,即8bit ,该情况下占用内存就是(字符长度)*8 。
若用哈弗曼编码,占用内存是各(字符频度)* (每个字符占用位数)之和。
2.3 关键算法分析该程序关键算法即哈弗曼编码,语句如下:void CHTree::huffmancode(){int i;if(n<=1)return;m=2*n-1;for(i=1;i<=n;i++)//叶子节点的初始化{ ht[i].parent=0;ht[i].lchild=0;ht[i].rchild=0;}for(;i<=m;i++) //非叶子节点的初始化{ht[i].weight=0;ht[i].parent=0;ht[i].lchild=0;ht[i].rchild=0;}-for(i=n+1;i<=m;++i)//构造哈夫曼树{s1=select(i-1);// 函数在 ht[1] 到 ht[i-1] 中选择 parent 为 0 且 weight 最小的结点,并将结点序号返 s,并将 ht[s1].parent 设为 -1s2=select(i-1);ht[s1].parent=i;ht[s2].parent=i;ht[i].lchild=s1;ht[i].rchild=s2;ht[i].weight=ht[s1].weight+ht[s2].weight;}int c,f;for(i=1;i<=n;++i) {for(c=i,f=ht[i].parent;f!=0;c=f,f=ht[f].parent)//逆向求叶子结点的哈夫曼编码if(ht[f].lchild==c){str[i].insert(0,"0",0,1);} //在字符串str[i] 的第 0 位置插入字符“ 0”else{str[i].insert(0,"1",0,1);} //在字符串str[i] 的第 0 位置插入字符“1”}}分析:这段语句实现的功能是根据统计出来的各字符的频度,建立哈弗曼。
建立哈弗曼树的过程如程序所展示,每次选取权重最小且无双亲节点的节点组合,并将其权重之和赋给其双亲节点,加入到总结中进行下次判断。
哈弗曼树建立完全以后,开始对各字符进行编码,从下往上,以叶子节点为起始点,若它是双亲节点的左孩子,其编码前插入‘0’,若是右孩子则插入‘ 1’。
再判断双亲节点使其双亲节点的左孩子还是右孩子,以此类推直到根节点。
依次对每个字符进行上述过程编码。
算法复杂度:最好情况为只有根结点和叶子节点:O( n)最坏情况为满二叉树情况:O( n*logn/2 )-3.程序运行结果分析首先,要求用户输入进行编码的字符串,遍历字符串,并为叶子节点权重赋值。
然后,依次对各字符进行哈弗曼编码,自下往上,若是双亲节点左孩子则编码前插入‘0’,若是双亲节点右孩子则编码钱插入‘ 1’。
屏幕上显示各字符的哈弗曼编码。
接下来对字符串进行编码,挨个遍历字符,找到相应的编码,复制到总的编码里,最后输出字符串的编码。
对字符串的哈弗曼码进行译码。
自上往下,若是‘0’,则递归到左孩子,若是‘1’,则递归到右孩子,知道叶子节点,输出该叶子节点代表字符,再继续遍历。
最后分析内存占用情况。
若用ASCII 编码,每个字符占 1 个字节,即8bit,该情况下占用内存就是(字符长度)*8 。
若用哈弗曼编码,占用内存是各(字符频度)*(每个字符占用位数)之和。
3.总结4.1 实验的难点和关键点本实验的难点和关键点是进行哈弗曼的编码与译码。
编码之前先要遍历字符串,并统计各字符出现的频度。
这里就要区分目前的字符是否出现过,若出现过则字符权重加一,若没有出现则在结构体数组的当前末尾添加该元素。
统计完频度以后开始编码。
根据哈弗曼树的特点,每次选取结点里权重最小,且双亲不为0 的节点结合,依次添加直至根节点。
编码过程是从下往上。
对于某字符所在叶子节点,若是双亲节点左孩子则编码前插入‘0’,若是双亲节点右孩子则编码钱插入‘ 1’。
直到双亲节点移动到根节点,所得到的编码即为该字符的编码。
译码过程是编码的逆过程。
依次读取哈弗曼码,自上往下,若是‘0’,则递归到左孩-子,若是‘ 1’,则递归到右孩子,知道叶子节点,输出该叶子节点代表字符,再继续遍历。
4.2 心得体会通过哈弗曼树的程序编写,更加深入了解了树这种数据结构的特点,并且熟悉了这种数据结构的应用。
同时,也对哈弗曼编码的优越性能有了根本的解释。
附:程序代码#include<iostream>#include<string>using namespace std;#define max 1000// 哈夫曼数存储的最大叶子节点数int judge;// 初始化过程中用于判断字符是否出现过struct HTNode{char c;int weight;int lchild,rchild,parent;};class CHTree{public:CHTree(){ht=NULL;} ;void Init();void huffmancode();int select(int i);void Display();void canculate();void encoding();void decoding();private:HTNode* ht;int m;int n;// 叶子结点数int s1;int s2;string a;// 存储输入的字符串string code;// 存储对字符串的编码string str[max];// 存储叶子结点的哈夫曼编码};void CHTree::Init()-{int i=1;// 用于记录叶子节点个数int j=0;int x=0,ru;cout<<" 请输入进行编码的字符串:"<<endl;cin>>a;int l=a.length();ht=(HTNode*)malloc((max)*sizeof(HTNode));//分配 MAXSIZE个叶子结点的存储空间while(x<l) // 统计字符出现的次数{judge=1;for(j=0;j<i;j++){if(ht[j].c==a[x]){//如果字符a[x]已经出现过,则记录,权值加1ht[j].weight++;judge=0;break;}}if(judge){// 若字符没有出现过,字符入列,且权值设为1 n=i;//记录叶子节点数ht[i].weight=1;ht[i].c=a[x];i++; }x++;}}int CHTree::select(int i)// 函数在 ht[1] 到 ht[i] 中选择 parent 为 0 且 weight 最小的结点,并将结点序号返回{int j=1;int k=1;int s;while(ht[j].parent!=0){j++;s=j;}k=j+1;while(k<=i){while(ht[k].parent!=0) k++;if(k>i)return s;if(ht[j].weight>ht[k].weight){ht[j].parent=0;// 如果第二次和第二次以后循环中发现有比ht[j] 权值还小的,将欢迎下载8-s=j;ht[j].parent=-1;// 如果 ht[j] 是权值较小的,将ht[j] 的 parent 记为 -1,}else{s=j;ht[j].parent=-1;}k++;}return s; }void CHTree::huffmancode(){int i;if(n<=1)return;m=2*n-1;for(i=1;i<=n;i++)//叶子节点的初始化{ ht[i].parent=0;ht[i].lchild=0;ht[i].rchild=0;}for(;i<=m;i++) //非叶子节点的初始化{ht[i].weight=0;ht[i].parent=0;ht[i].lchild=0;ht[i].rchild=0;}for(i=n+1;i<=m;++i)//构造哈夫曼树{s1=select(i-1);// 函数在 ht[1] 到 ht[i-1] 中选择 parent 为 0 且 weight 最小的结点,并将结点序号返 s,并将 ht[s1].parent 设为 -1s2=select(i-1);ht[s1].parent=i;ht[s2].parent=i;ht[i].lchild=s1;ht[i].rchild=s2;ht[i].weight=ht[s1].weight+ht[s2].weight;}int c,f;for(i=1;i<=n;++i) {for(c=i,f=ht[i].parent;f!=0;c=f,f=ht[f].parent)//逆向求叶子结点的哈夫曼编码if(ht[f].lchild==c){str[i].insert(0,"0",0,1);} //在字符串str[i] 的第 0 位置插入字符“ 0”else{str[i].insert(0,"1",0,1);} //在字符串str[i] 的第 0 位置插入字符“1”}-void CHTree::Display(){cout<<"huffman 编码如下: \n";cout<<" 字符 "<<'\t'<<" 权值 "<<'\t'<<" 哈夫曼编码 "<<endl;for(int i=1;i<=n;i++){cout<<ht[i].c<<'\t'<<ht[i].weight<<'\t'<<str[i]<<endl;}}void CHTree::canculate(){int m=0;for(int i=1;i<=n;i++){m+=(ht[i].weight)*(str[i].length());//该字符所占位数为频度和每个字符huffman 码长度乘积}cout<<"\n\n内存分析:\n"<<"原始编码所占内存数为"<<8*sizeof(char)*(a.length())<<"bit"<<endl;cout<<"huffman 编码所占内存数为"<<m<<"bit"<<endl;}void CHTree::encoding(){for(int i=0;i<a.length();i++){//循环变量i用于遍历输入字符串的字符for(int j=1;j<=n;j++){//循环变量j用于寻找huffman编码中与该字符的相匹配的字符编码if(a[i]==ht[j].c)code+=str[j];}}cout<<"\n\n 字符编码为 "<<code<<endl;}void CHTree::decoding(){int i=0;int m=code.length();cout<<"\n\n 对编码译码后所得字符:";while(i<m){int parent=2*n-1;// 根结点在 HTree 中的下表while(ht[parent].rchild!=0||ht[parent].lchild!=0)// 自根结点向叶子节点匹配编码,叶子节点左右孩子均为0,此时输出字符{if(code[i]=='0')parent=ht[parent].lchild;elseparent=ht[parent].rchild;i++;}cout<<ht[parent].c;}-}void main(){CHTree h;h.Init(); // 初始化,统计输入字符的频度,赋值各叶子节点的权重h.huffmancode();// 建立 huffman 树h.Display();// 显示各字符对应的huffman 码h.encoding();// 对输入的字符进行编码h.decoding();// 对以上编码进行解码h.canculate();// 计算分析编码前与编码后的所占内存system("pause");}。