哈工大数据结构大作业——哈夫曼树生成、编码、遍历
数据结构实验哈夫曼树编码

实验四哈夫曼树编码一、实验目的1、掌握哈夫曼树的一般算法;2、掌握用哈夫曼树对字符串进行编码;3、掌握通过哈夫曼树对字符编码进行译码得过程。
二、实验基本要求1、设计数据结构;2、设计编码算法;3、分析时间复杂度和空间复杂度三、程序实现此程序中包含六个函数:Select()、HuffmanTree()、BianMa()、BianMa2()、YiMa()、Sum(),其功能及实现过程如下:#include <iostream.h>struct element//哈夫曼树结点类型{int weight;int lchild,rchild,parent;};struct Char//字符编码表信息{char node;int weight;char code[20];};void Select(element hT[],int &i1,int &i2,int k)//在hT[]中查找最小值及次小值{int min1=9999,min2=9999;i1=i2=0;for(int i=0;i<k;i++)if(hT[i].parent==-1)if(hT[i].weight<min1){min2=min1;i2=i1;min1=hT[i].weight;i1=i;}else if(hT[i].weight<min2){min2=hT[i].weight;i2=i;}}void HuffmanTree(element huffTree[],Char zifuma[],int n) //构建哈夫曼树{int i,k,i1,i2;for(i=0;i<2*n-1;i++) //初始化{huffTree[i].parent=-1;huffTree[i].lchild=-1;huffTree[i].rchild=-1;}for(i=0;i<n;i++) //构造n棵只含有根结点的二叉树huffTree[i].weight=zifuma[i].weight;for(k=n;k<2*n-1;k++) //n-1次合并{Select(huffTree,i1,i2,k); //在huffTree中找权值最小的两个结点i1和i2huffTree[i1].parent=k; //将i1和i2合并,则i1和i2的双亲是khuffTree[i2].parent=k;huffTree[k].weight=huffTree[i1].weight+huffTree[i2].weight;huffTree[k].lchild=i1;huffTree[k].rchild=i2;}}void BianMa(element huffTree[],Char zifuma[],int n)//根据哈夫曼树编码{int i,m,k,j,l;char temp[20];if(n==1){ zifuma[0].code[0]='0';zifuma[0].code[1]=0;}else {for(i=0;i<n;i++){j=0;k=huffTree[i].parent;l=i;while(k!=-1){if(huffTree[k].lchild==l)temp[j++]='0';else temp[j++]='1';l=k;k=huffTree[k].parent;}k=j-1;for(m=0;m<j;m++)zifuma[i].code[m]=temp[k--];zifuma[i].code[m]=0;}}void BianMa2(Char zifuma[],char zifu[],char bianma[],int n)//根据编码表对字符串编码{int i,j,k,m;i=k=0;while(zifu[i]){for(j=0;j<n;j++)if(zifu[i]==zifuma[j].node){m=0;while(zifuma[j].code[m])bianma[k++]=zifuma[j].code[m++];}i++;}bianma[k]=0;}void YiMa(element huffTree[],Char zifuma[],char bianma[],char yima[],int n)//根据编号的码元译成字符串{int i,j,k;i=j=0;if(n==1)while(bianma[i++])yima[j++]=zifuma[0].node;else{while(bianma[i]){k=2*(n-1);while(!(huffTree[k].lchild==-1&&huffTree[k].rchild==-1))if(bianma[i++]=='0')k=huffTree[k].lchild;elsek=huffTree[k].rchild;yima[j++]=zifuma[k].node;}}yima[j]=0;}void Sum(char zifu[],Char bianma[],int &n)//计算字符串中字符种类的个数及其出现次数{i=j=0;while(zifu[i]){for(int k=0;k<j;k++)if(bianma[k].node==zifu[i]){bianma[k].weight++;break;}if(k==j){bianma[j].node=zifu[i];bianma[j++].weight=1;}i++;}n=j;}void main(){int n,i;char a[50],b[200],c[50];element huffTree[100];Char w[50];cout<<"请输入需要编码的字符串:\n";cin.getline(a,49);Sum(a,w,n);cout<<"该字符串中共有"<<n<<"类字符。
数据结构:哈夫曼树和哈夫曼编码

数据结构:哈夫曼树和哈夫曼编码哈夫曼树哈夫曼树是⼀种最优⼆叉树,其定义是:给定n个权值作为n个叶⼦节点,构造⼀棵⼆叉树,若树的带权路径长度达到最⼩,这样的树就达到最优⼆叉树,也就是哈夫曼树,⽰例图如下:基本概念深⼊学习哈夫曼树前,先了解⼀下基本概念,并以上⾯的哈夫曼树图为例路径:树中⼀个结点到另⼀个结点之间的分⽀序列构成两个结点间的路径。
路径长度:路径中分⽀的数⽬,从根结点到第L层结点的路径长度为L-1。
例如100和80的路径长度为1,50和30的路径长度为2。
结点的权:树中结点的数值,例如100,50那些。
结点带权路径长度:根结点到该结点之间的路径长度与该结点的权的乘积。
如结点20的路径长度为3,该结点的带权路径长度为:3*20 = 60。
树的带权路径长度:所有叶⼦结点的带权路径长度之和,记为WPL。
例如上图树的WPL = 1100 + 280 +320 +310 = 350。
带权路径长度⽐较前⾯说到,哈夫曼树是最优⼆叉树,因为符合哈夫曼树特点的树的带权路径长度⼀定是最⼩的,我们将哈夫曼树和普通的⼆叉树做个⽐较,仍以上图为例,上图的哈夫曼树是结点10,20,50,100组成的⼆叉树,WPL是350,⽤这四个结点组成普通的⼆叉树,结果如下:不难计算,该⼆叉树的WPL = 210 + 220 + 250 + 2100 = 360,明显⽐哈夫曼树⼤,当然⼆叉树的组成结果不唯⼀,但WPL⼀定⽐哈夫曼树⼤。
所以说哈夫曼树是最优⼆叉树。
哈夫曼树的构造现在假定有n个权值,设为w1、w2、…、wn,将这n个权值看成是有n棵树的森林,根据最⼩带权路径长度的原则,我们可以按照下⾯步骤来将森林构造成哈夫曼树:1. 在森林中选出根结点的权值最⼩的两棵树进⾏合并,作为⼀棵新树的左、右⼦树,且新树的根结点权值为其左、右⼦树根结点权值之和;2. 从森林中删除选取的两棵树,并将新树加⼊森林;3. 重复1、2步,直到森林中只剩⼀棵树为⽌,该树即为所求得的哈夫曼树。
数据结构哈夫曼树的代码

数据结构哈夫曼树的代码数据结构哈夫曼树1.概述哈夫曼树(Huffman Tree)是一种经典的树形数据结构,用于编码和解码。
它根据各个字符出现的频率构建一个最优的前缀编码树,使得频率较高的字符具有较短的编码,频率较低的字符具有较长的编码。
2.哈夫曼树的构建2.1 频率统计首先,需要对给定的数据进行频率统计。
遍历数据集,记录每个字符的出现频率。
2.2 构建优先队列将频率统计得到的字符和各自的频率构建成一个优先队列。
队列中的每个元素都是一个字符及其频率的结构体。
2.3 构建哈夫曼树通过不断合并优先队列中频率最小的两个节点,构建出一棵哈夫曼树。
合并的过程中,新节点的频率为两个子节点频率之和。
2.4 构建哈夫曼编码从哈夫曼树的根节点出发,分别向左和向右遍历每个节点,直到叶子节点。
记录路径中经过的方向,0表示向左,1表示向右,获取每个字符的编码。
编码的长度即为该字符的出现频率。
3.哈夫曼树的应用3.1 数据压缩由于哈夫曼编码具有前缀码的特性,使得压缩后的数据可以唯一地解码回原始数据。
利用哈夫曼编码对数据进行压缩,可以减小存储空间的占用。
3.2 数据传输哈夫曼编码也广泛应用于数据传输领域。
由于编码的长度与频率成正比,频率较高的字符具有较短的编码,传输过程中能够减小数据传输的时间和带宽占用。
4.示例代码下面是一个用C++实现的简单哈夫曼树代码示例:________```cppinclude <iostream>include <queue>using namespace std。
struct Node {char data。
// 字符int freq。
// 频率Node left。
Node right。
}。
struct compare {bool operator(Node l, Node r) {return (l->freq > r->freq)}}。
void printCodes(Node root, string str) { if (!root)return。
哈夫曼树 哈夫曼编码(先序遍历方法)

for(i=0;i<2*n-1;i++)
{
printf("%d,", Huffman[i]->weight);
}
printf("\n");
for(i=0;i<2*n-1;i++)
{
printf("%d的左结点的下标为%d,右结点的下标为%d\n",Huffman[i]->weight,Huffman[i]->left,Huffman[i]->right);
{
if(i==1 && k==0 )
{
q[i] = Huffman[x];
s[i-1] = '*';
k++;
}
while(q[i]->left !=-1 && ls[i] == 0)
{
x =Huffman[x]->left;
ls[i] = 1; i++; k++;
q[i] = Huffman[x];
{
m1 = Huffman[j]->weight ;
x1 = j;
}
}
for(j=0;j<n+i;j++)
{
if( Huffman[j]->weight < m2 && Huffman[j]->parent == -1 && x1 != j)
{
m2 = Huffman[j]->weight ;
x2 = j;
tree Huffman[100];
哈夫曼树_实验报告

一、实验目的1. 理解哈夫曼树的概念及其在数据结构中的应用。
2. 掌握哈夫曼树的构建方法。
3. 学习哈夫曼编码的原理及其在数据压缩中的应用。
4. 提高编程能力,实现哈夫曼树和哈夫曼编码的相关功能。
二、实验原理哈夫曼树(Huffman Tree)是一种带权路径长度最短的二叉树,又称为最优二叉树。
其构建方法如下:1. 将所有待编码的字符按照其出现的频率排序,频率低的排在前面。
2. 选择两个频率最低的字符,构造一棵新的二叉树,这两个字符分别作为左右子节点。
3. 计算新二叉树的频率,将新二叉树插入到排序后的字符列表中。
4. 重复步骤2和3,直到只剩下一个节点,这个节点即为哈夫曼树的根节点。
哈夫曼编码是一种基于哈夫曼树的编码方法,其原理如下:1. 从哈夫曼树的根节点开始,向左子树走表示0,向右子树走表示1。
2. 每个叶子节点对应一个字符,记录从根节点到叶子节点的路径,即为该字符的哈夫曼编码。
三、实验内容1. 实现哈夫曼树的构建。
2. 实现哈夫曼编码和译码功能。
3. 测试实验结果。
四、实验步骤1. 创建一个字符数组,包含待编码的字符。
2. 创建一个数组,用于存储每个字符的频率。
3. 对字符和频率进行排序。
4. 构建哈夫曼树,根据排序后的字符和频率,按照哈夫曼树的构建方法,将字符和频率插入到哈夫曼树中。
5. 实现哈夫曼编码功能,遍历哈夫曼树,记录从根节点到叶子节点的路径,即为每个字符的哈夫曼编码。
6. 实现哈夫曼译码功能,根据哈夫曼编码,从根节点开始,按照0和1的路径,找到对应的叶子节点,即为解码后的字符。
7. 测试实验结果,验证哈夫曼编码和译码的正确性。
五、实验结果与分析1. 构建哈夫曼树根据实验数据,构建的哈夫曼树如下:```A/ \B C/ \ / \D E F G```其中,A、B、C、D、E、F、G分别代表待编码的字符。
2. 哈夫曼编码根据哈夫曼树,得到以下字符的哈夫曼编码:- A: 00- B: 01- C: 10- D: 11- E: 100- F: 101- G: 1103. 哈夫曼译码根据哈夫曼编码,对以下编码进行译码:- 00101110111译码结果为:BACGACG4. 实验结果分析通过实验,验证了哈夫曼树和哈夫曼编码的正确性。
哈夫曼树的编码和解码

哈夫曼树的编码和解码是哈夫曼编码算法的重要部分,下面简要介绍其步骤:
1. 编码:
哈夫曼编码是一种变长编码方式,对于出现频率高的字符使用较短的编码,而对于出现频率低的字符使用较长的编码。
具体步骤如下:(1)根据字符出现的频率,构建哈夫曼树。
频率相同的字符,按照它们在文件中的出现顺序排列。
(2)从哈夫曼树的叶子节点开始,从下往上逐步进行编码。
对于每个节点,如果该节点有左孩子,那么左孩子的字符编码为0,右孩子的字符编码为1。
如果该节点是叶子节点,则该节点的字符就是它的编码。
(3)对于哈夫曼树中的每个节点,都记录下它的左孩子和右孩子的位置,以便后续的解码操作。
2. 解码:
解码过程与编码过程相反,具体步骤如下:
(1)从哈夫曼树的根节点开始,沿着路径向下遍历树,直到找到一个终止节点(叶节点)。
(2)根据终止节点的位置信息,找到对应的字符。
(3)重复上述步骤,直到遍历完整个编码序列。
需要注意的是,哈夫曼编码是一种无损压缩算法,解压缩后的数据与原始数据完全相同。
此外,由于哈夫曼编码是一种变长编码方式,因此在解码时需要从根节点开始逐个解码,直到解码完成。
数据结构 哈夫曼编码实验报告

数据结构哈夫曼编码实验报告数据结构哈夫曼编码实验报告1. 实验目的本实验旨在通过实践理解哈夫曼编码的原理和实现方法,加深对数据结构中树的理解,并掌握使用Python编写哈夫曼编码的能力。
2. 实验原理哈夫曼编码是一种用于无损数据压缩的算法,通过根据字符出现的频率构建一棵哈夫曼树,并根据哈夫曼树对应的编码。
根据哈夫曼树的特性,频率较低的字符具有较长的编码,而频率较高的字符具有较短的编码,从而实现了对数据的有效压缩。
实现哈夫曼编码的主要步骤如下:1. 统计输入文本中每个字符的频率。
2. 根据字符频率构建哈夫曼树,其中树的叶子节点代表字符,内部节点代表字符频率的累加。
3. 遍历哈夫曼树,根据左右子树的关系对应的哈夫曼编码。
4. 使用的哈夫曼编码对输入文本进行编码。
5. 将编码后的二进制数据保存到文件,同时保存用于解码的哈夫曼树结构。
6. 对编码后的文件进行解码,还原原始文本。
3. 实验过程3.1 统计字符频率首先,我们需要统计输入文本中每个字符出现的频率。
可以使用Python中的字典数据结构来记录字符频率。
遍历输入文本的每个字符,将字符添加到字典中,并递增相应字符频率的计数。
```pythondef count_frequency(text):frequency = {}for char in text:if char in frequency:frequency[char] += 1else:frequency[char] = 1return frequency```3.2 构建哈夫曼树根据字符频率构建哈夫曼树是哈夫曼编码的核心步骤。
我们可以使用最小堆(优先队列)来高效地构建哈夫曼树。
首先,将每个字符频率作为节点存储到最小堆中。
然后,从最小堆中取出频率最小的两个节点,将它们作为子树构建成一个新的节点,新节点的频率等于两个子节点频率的和。
将新节点重新插入最小堆,并重复该过程,直到最小堆中只剩下一个节点,即哈夫曼树的根节点。
数据结构哈夫曼树实验报告

数据结构哈夫曼树实验报告一、实验内容本次实验的主要内容是哈夫曼树的创建和编码解码。
二、实验目的1. 理解并掌握哈夫曼树的创建过程;2. 理解并掌握哈夫曼编码的原理及其实现方法;3. 掌握哈夫曼树的基本操作,如求哈夫曼编码和哈夫曼解码等;4. 学习如何组织程序结构,运用C++语言实现哈夫曼编码和解码。
三、实验原理哈夫曼树的创建:哈夫曼树的创建过程就是一个不断合并权值最小的两个叶节点的过程。
具体步骤如下:1. 将所有节点加入一个无序的优先队列里;2. 不断地选出两个权值最小的节点,并将它们合并成为一个节点,其权值为这两个节点的权值之和;3. 将新的节点插入到队列中,并继续执行步骤2,直到队列中只剩下一棵树,这就是哈夫曼树。
哈夫曼编码:哈夫曼编码是一种无损压缩编码方式,它根据字符出现的频率来构建编码表,并通过编码表将字符转换成二进制位的字符串。
具体实现方法如下:1. 统计每个字符在文本中出现的频率,用一个数组记录下来;2. 根据字符出现的频率创建哈夫曼树;3. 从根节点开始遍历哈夫曼树,给左分支打上0的标记,给右分支打上1的标记。
遍历每个叶节点,将对应的字符及其对应的编码存储在一个映射表中;4. 遍历文本中的每个字符,查找其对应的编码表,并将编码字符串拼接起来,形成一个完整的编码字符串。
哈夫曼解码就是将编码字符串还原为原始文本的过程。
具体实现方法如下:1. 从根节点开始遍历哈夫曼树,按照编码字符串的位数依次访问左右分支。
如果遇到叶节点,就将对应的字符记录下来,并重新回到根节点继续遍历;2. 重复步骤1,直到编码字符串中的所有位数都被遍历完毕。
四、实验步骤1. 定义编码和解码的结构体以及相关变量;3. 遍历哈夫曼树,得到每个字符的哈夫曼编码,并将编码保存到映射表中;4. 将文本中的每个字符用其对应的哈夫曼编码替换掉,并将编码字符串写入到文件中;5. 使用哈夫曼编码重新构造文本,并将结果输出到文件中。
五、实验总结通过本次实验,我掌握了哈夫曼树的创建和哈夫曼编码的实现方法,也学会了如何用C++语言来组织程序结构,实现哈夫曼编码和解码。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一、问题描述1.用户输入字母及其对应的权值,生成哈夫曼树;2.通过最优编码的算法实现,生成字母对应的最优0、1编码;3.先序、中序、后序遍历哈夫曼树,并打印其权值。
二、方法思路1.哈夫曼树算法的实现§存储结构定义#define n 100 /* 叶子树*/#define m 2*(n) –1 /* 结点总数*/typedef struct { /* 结点型*/double weight ; /* 权值*/int lchild ; /* 左孩子链*/int rchild ; /* 右孩子链*/int parent; /* 双亲链*/ 优点?}HTNODE ;typedef HTNODE HuffmanT[ m ] ;/* huffman树的静态三叉链表表示*/算法要点1)初始化:将T[0],…T[m-1]共2n-1个结点的三个链域均置空( -1 ),权值为0;2)输入权值:读入n 个叶子的权值存于T的前n 个单元T[0],…T[n], 它们是n 个独立的根结点上的权值;3)合并:对森林中的二元树进行n-1次合并,所产生的新结点依次存放在T[i](n<=i<=m-1)。
每次合并分两步:(1) 在当前森林中的二元树T [0],…T[i-1]所有结点中选取权值最小和次最小的两个根结点T[p1]和T[p2]作为合并对象,这里0<= p1,p2<= i –1;(2) 将根为T[p1]和T[p2]的两株二元树作为左、右子树合并为一株新二元树,新二元树的根结点为T[i]。
即T[p1].parent =T[p2].parent = i ,T[i].lchild= p1,T[i].rchild=p2,T[i].weight =T[p1].weight +T[p2].weight。
2.用huffman算法求字符集最优编码的算法:1) 使字符集中的每个字符对应一株只有叶结点的二叉树,叶的权值为对应字符的使用频率;2) 利用huffman算法来构造一株huffman树;3) 对huffman树上的每个结点,左支附以0,右支附以1(或者相反),则从根到叶的路上的0、1序列就是相应字符的编码Huffman编码实现:存储结构typedef struct{char ch; //存储字符char bits[n+1]; //字符编码位串}CodeNode;typedef CodeNode HuffmanCode[n];HuffmanCode H;3.二叉树遍历的递归定义先根顺序遍历二叉树:若二叉树非空则:{访问根结点;先根顺序遍历左子树;先根顺序遍历右子树;}中根顺序遍历二叉树:若二叉树非空则:{中根顺序遍历左子树;访问根结点;中根顺序遍历右子树;}后根顺序遍历二叉树:若二叉树非空则:{ 后根顺序遍历左子树;后根顺序遍历右子树;访问根结点;} ;三、主要数据结构及源程序代码及其注释1.扩充二叉树:内结点、外结点(增长树)2.哈夫曼树3.Huffman编码实现源程序代码及注释#include"stdafx.h"#include<stdio.h>#include<string.h>#include<stdlib.h>#define n 10#define m 2*(n)-1typedef struct//建立哈夫曼结点结构体{char data;float weight;int lchild;int rchild;int parent;}htnode;typedef struct//建立哈夫曼编码结构体{char ch;char bits[n+1];}htcode;void SelectMin(htnode T[m],int nn,int&p1,int&p2)//选择哈夫曼树所有结点中权值最小的两个根结点{int i,j;for(i=0;i<=nn;i++){if(T[i].parent==-1){p1=i;break;}}for(j=i+1;j<=nn;j++){if(T[j].parent==-1){p2=j;break;}}for(i=0;i<=nn;i++){if((T[p1].weight>T[i].weight)&&(T[i].parent==-1)&&(p2!=i))p1=i;}for(j=0;j<=nn;j++){if((T[p2].weight>T[j].weight)&&(T[j].parent==-1)&&(p1!=j))p2=j;}}void CreatHT(htnode T[m])//建立哈夫曼树{int i,p1,p2;for(i=0;i<m;i++){T[i].parent=T[i].lchild=T[i].rchild=-1;//赋初值}for(i=n;i<m;i++){SelectMin(T,i-1,p1,p2);T[p1].parent=T[p2].parent=i;if(T[p1].weight<T[p2].weight){T[i].lchild=p1;T[i].rchild=p2;}else{T[i].lchild=p2;T[i].rchild=p1;}T[i].weight=T[p1].weight+T[p2].weight;}}void HuffmanEncoding(htnode T[m],htcode C[n])//哈夫曼编码{int c,p,i;char cd[n+1];int start;cd[n]='\0';//结束表示for(i=0;i<n;i++){C[i].ch=T[i].data;start=n;c=i;while((p=T[c].parent)>=0){start=start-1;if(T[p].lchild==c){cd[start]='0';}else{cd[start]='1';}c=p;}strcpy(C[i].bits,&cd[start]);}}void preorder(htnode T[],int i)//先序遍历哈夫曼树:递归的办法{printf("%f",T[i].weight);if(T[i].lchild!=-1){preorder(T,T[i].lchild);preorder(T,T[i].rchild);}}void inorder(htnode T[],int i)//中序遍历哈夫曼树{if(T[i].lchild!=-1){inorder(T,T[i].lchild);printf("%f",T[i].weight);inorder(T,T[i].rchild);}else{printf("%f",T[i].weight);//防止左儿子为空,程序退出}}void postorder(htnode T[],int i)//后序遍历哈夫曼树{if(T[i].lchild!=-1){postorder(T,T[i].lchild);postorder(T,T[i].rchild);printf("%f",T[i].weight);}else{printf("%f",T[i].weight);//防止左儿子为空,程序退出}}void main(){int i;int j;j=m-1;htnode T[m];htcode C[n];htnode *b;printf("Input 10 elements and weights:");for (i=0;i<n;i++)//用户输入字母及对应的权值{printf("Input NO.%d element:\n",i);scanf(" %c",&T[i].data);printf("Input the weight of NO.%d element:\n",i);scanf(" %f",&T[i].weight);}CreatHT(T);//建立哈夫曼树HuffmanEncoding(T,C);//建立哈夫曼编码printf("Output Huffman coding:\n");for (i=0;i<n;i++){printf("%c:",C[i].ch);printf("%s\n",C[i].bits);}printf("Output Haffman Tress in preorder way:\n");preorder(T,j);//先序遍历哈夫曼树printf("\n");printf("Output Haffman Tress in inorder way:\n");//中序遍历哈夫曼树inorder(T,j);printf("Output Haffman Tress in postorder way:\n");//后序遍历哈夫曼树postorder(T,j);while(1);//运行结果停止在当前画面}四、运行结果#include"stdafx.h"#include<stdio.h>#include<string.h>#include<stdlib.h>#define n 10#define m 2*(n)-1typedef struct//建立哈夫曼结点结构体{char data;float weight;int lchild;int rchild;int parent;}htnode;typedef struct//建立哈夫曼编码结构体{char ch;char bits[n+1];}htcode;void SelectMin(htnode T[m],int nn,int&p1,int&p2)//选择哈夫曼树所有结点中权值最小的两个根结点{int i,j;for(i=0;i<=nn;i++){if(T[i].parent==-1){p1=i;break;}}for(j=i+1;j<=nn;j++){if(T[j].parent==-1){p2=j;break;}}for(i=0;i<=nn;i++){if((T[p1].weight>T[i].weight)&&(T[i].parent==-1)&&(p2!=i))p1=i;}for(j=0;j<=nn;j++){if((T[p2].weight>T[j].weight)&&(T[j].parent==-1)&&(p1!=j))p2=j;}}void CreatHT(htnode T[m])//建立哈夫曼树{int i,p1,p2;for(i=0;i<m;i++){T[i].parent=T[i].lchild=T[i].rchild=-1;//赋初值}for(i=n;i<m;i++){SelectMin(T,i-1,p1,p2);T[p1].parent=T[p2].parent=i;if(T[p1].weight<T[p2].weight){T[i].lchild=p1;T[i].rchild=p2;}else{T[i].lchild=p2;T[i].rchild=p1;}T[i].weight=T[p1].weight+T[p2].weight;}}void HuffmanEncoding(htnode T[m],htcode C[n])//哈夫曼编码{int c,p,i;char cd[n+1];int start;cd[n]='\0';//结束表示for(i=0;i<n;i++){C[i].ch=T[i].data;start=n;c=i;while((p=T[c].parent)>=0){start=start-1;if(T[p].lchild==c){cd[start]='0';}else{cd[start]='1';}c=p;}strcpy(C[i].bits,&cd[start]);}}void preorder(htnode T[],int i)//先序遍历哈夫曼树:递归的办法{printf("%f",T[i].weight);if(T[i].lchild!=-1){preorder(T,T[i].lchild);preorder(T,T[i].rchild);}}void inorder(htnode T[],int i)//中序遍历哈夫曼树{if(T[i].lchild!=-1){inorder(T,T[i].lchild);printf("%f",T[i].weight);inorder(T,T[i].rchild);}else{printf("%f",T[i].weight);//防止左儿子为空,程序退出}}void postorder(htnode T[],int i)//后序遍历哈夫曼树{if(T[i].lchild!=-1){postorder(T,T[i].lchild);postorder(T,T[i].rchild);printf("%f",T[i].weight);}else{printf("%f",T[i].weight);//防止左儿子为空,程序退出}}void main(){int i;int j;j=m-1;htnode T[m];htcode C[n];htnode *b;printf("Input 10 elements and weights:");for (i=0;i<n;i++)//用户输入字母及对应的权值{printf("Input NO.%d element:\n",i);scanf(" %c",&T[i].data);printf("Input the weight of NO.%d element:\n",i);scanf(" %f",&T[i].weight);}CreatHT(T);//建立哈夫曼树HuffmanEncoding(T,C);//建立哈夫曼编码printf("Output Huffman coding:\n");for (i=0;i<n;i++){printf("%c:",C[i].ch);printf("%s\n",C[i].bits);}printf("Output Haffman Tress in preorder way:\n");preorder(T,j);//先序遍历哈夫曼树printf("\n");printf("Output Haffman Tress in inorder way:\n");//中序遍历哈夫曼树inorder(T,j);printf("Output Haffman Tress in postorder way:\n");//后序遍历哈夫曼树postorder(T,j);while(1);//运行结果停止在当前画面}。