二叉树和哈夫曼树实验报告

合集下载

数据结构实验报告3-二叉树

数据结构实验报告3-二叉树

北京物资学院信息学院实验报告课程名数据结构(C++)实验实验名称二叉树算法的实现实验日期年月日实验报告日期年月日姓名______ ___ 班级_____ _______ 学号___一、实验目的1.掌握二叉树的存储的结构;2. 掌握建立二叉树的算法;3. 掌握对二叉树的遍历算法;4. 掌握二叉搜索树的算法;5. 掌握建立哈夫曼树和哈夫曼编码的算法;二、实验内容基本部分1. 采用广义表形式建立二叉树(参考图5-11(a)和/或图5-13(a));2. 对已建立的二叉树,进行先、中、后序和按层遍历;3. 用广义表形式输出二叉树;4. 【习题5-3】1, 2 (2题选作)【提示:参考递归遍历算法】;特殊二叉树部分1.用插入算法建立一棵二叉搜索树,原始数据为:{30,50,20,40,25,70,54,23,80,92},并中序遍历该树、查找其中的元素;2. 构造一棵叶子结点权值分别为3,5,6,7,9,13,21的哈夫曼树;3. 对2题进行哈夫曼编码。

三、实验地点与环境3.1 实验地点(南实验楼教室)3.2实验环境(所用语言环境)四、实验步骤1.2.3.…五、实验结果与分析5.1 实验结果(原始数据,预期结果和运行结果)序号算法名称(函数名) 所在头文件名原始数据与与功能主函数所在文件名运行结果*1 函数名:功能:头文件:CPP文件:原始数据:运行结果:23* 如果不能按“原始数据”、“运行结果”列出数据则不列,必要时在“分析”部分说明5.2 分析(选择部分算法分析,包括函数参数说明、调试中所遇到的问题和解决方法、中间结果等,必要时给出函数和主函数的关键段落。

所选算法应是:重要的算法、有编程特点的算法等)六、小结(收获与心得)。

数据结构实验报告《五、最优二叉树应用之哈夫曼编译码》

数据结构实验报告《五、最优二叉树应用之哈夫曼编译码》

数据结构实验报告《五、最优二叉树应用之哈夫曼编译码》数据结构实验报告- - - -最优二叉树运用--哈夫曼编/译码专业班级:电信0903时间:2011年11月27日数据结构实验报告----最优二叉树运用--哈夫曼编/译码【问题描述】例3(实验二方案3):设字符集为26个英文字母,其出现频度如下表所示。

先建哈夫曼树,再利用此树对报文“This program is my favorite”进行编码和译码。

注:若圆满实现了此方案,平时成绩将以满分计。

字符 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) I:初始化(Initialization)。

从终端读入字符集大小n,以及n个字符和n个权值,建立赫夫曼树,并将它存于文件hfmTree中。

(2) E:编码(Encoding)。

利用已建好的赫夫曼树(如不在内存,则从文件hfmTree中读入),对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中。

(3) D:译码(Decoding)。

利用已建好的赫夫曼树将文件CodeFile中的代码进行译码,结果存入文件Textfile中。

【运用拓展】(1) 编码结果以文本方式存储在文件Codefile中,(2) 仿真友好界面,用户界面可以设计为“菜单”方式,通过人机交互方式使用本程序,从而更加方便友好;【设计思路分析】1、将哈夫曼树节点的数据类型定义为: ?typedef struct{ //赫夫曼树的结构体char ch;int weight; //权值int parent,lchild,rchild;}htnode,*hfmtree;2、功能函数模块划分 ?1、void HfmCoding(HfmTree &HT,HfmCode &HC,int n)初始化哈夫曼树,按照哈夫曼规则建立2叉树。

树与二叉树实验

树与二叉树实验
{
int n=0;
if(tree==NULL)
return(0);
if(tree->lTree!=NULL&&tree->rTree!=NULL)
n=1;
return(Twochild(tree->lTree)+Twochild(tree->rTree)+n);
}
实验结果截图:
2、哈夫曼编码
2、哈夫曼编码
【实验目的】
了解赫夫曼树的结构特点及有关概念,掌握赫夫曼树的建立和赫夫曼编码的设计
【问题描述】
使用二叉树进行赫夫曼编码的设计,要求对输入的一串电文字符实现赫夫曼编码,再对赫夫编码生成的代码串进行译码,输出电文字符串
【实验功能】
1、赫夫曼树的建立:从终端读入字符集大小n,以及n个字符和n个权值,建立赫夫曼树,并将它存于文件hfmtree中;
PreTraverse(&tree);//先序遍历递归
cout<<"先序遍历非递归:";
PreOrderTraverse(&tree);//先序遍历非递归
cout<<endl;
cout<<"中序遍历递归为:";
InTraverse(&tree);//中序遍历递归
cout<<"中序遍历非递归:";
InOrderTraverse(&tree);//中序遍历非递归
}
else
cout<<tree->data<<" ";
}
}
void InOrderTraverse(Tree *tree)//中序遍历非递归

哈夫曼树实验报告

哈夫曼树实验报告

数据结构实验报告实验名称:实验三哈夫曼树学生姓名:班级:班内序号:学号:日期:程序分析:2.1 存储结构:二叉树2.2 程序流程:template <class T>class BiTree{public:BiTree(); //构造函数,其前序序列由键盘输入 ~BiTree(void); //析构函数BiNode<T>* Getroot(); //获得指向根结点的指针protected:BiNode<T> *root; //指向根结点的头指针};//声明类BiTree及定义结构BiNodeData:二叉树是由一个根结点和两棵互不相交的左右子树构成二叉树中的结点具有相同数据类型及层次关系哈夫曼树类的数据域,继承节点类型为int的二叉树class HuffmanTree:public BiTree<int>data:HCode* HCodeTable;//编码表int tSize; //编码表中的总字符数二叉树的节点结构template <class T>struct BiNode //二叉树的结点结构{T data; //记录数据T lchild; //左孩子T rchild; //右孩子T parent; //双亲};编码表的节点结构struct HCode{char data; //编码表中的字符char code[100]; //该字符对应的编码};待编码字符串由键盘输入,输入时用链表存储,链表节点为struct Node{char character; //输入的字符unsigned int count;//该字符的权值bool used; //建立树的时候该字符是否使用过Node* next; //保存下一个节点的地址};示意图:2.3 关键算法分析:1.初始化函数(void HuffmanTree::Init(string Input))算法伪代码:1.初始化链表的头结点2.获得输入字符串的第一个字符,并将其插入到链表尾部,n=1(n记录的是链表中字符的个数)3.从字符串第2个字符开始,逐个取出字符串中的字符3.1 将当前取出的字符与链表中已经存在的字符逐个比较,如果当前取出的字符与链表中已经存在的某个字符相同,则链表中该字符的权值加1。

哈夫曼树实验报告

哈夫曼树实验报告

哈夫曼树实验报告一、问题描述利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。

但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将穿来的数据进行译码,此试验即设计这样的一个简单的编/译码系统。

系统应该具有如下的几个功能。

1. 接受原始数据从终端任意读入字母,求出其各自的权重值,建立哈夫曼树,并将它存于hfmtree.dat文件中。

2. 编码利用已建好的哈夫曼树,对文件中的正文进行编码,然后将结果存入codefile.dat中。

3. 译码利用已建好的哈夫曼树将文件codefile.dat中的代码进行译码,结果存入文件textfile.dat中。

4. 打印编码规则即字符与编码的一一对应关系。

5. 打印哈夫曼树将已存在内存中的哈夫曼树以直观的方式显示在终端上。

二、数据结构设计1. 构造哈夫曼树时使用静态量表作为哈夫曼树的存储。

在构造哈夫曼树时,设计一个结构体数组HuffNode保存哈夫曼树中各节点的信息,根据二叉树的性质可知,具有n个叶子节点的哈夫曼树共有2n-1个结点,所以数组HuffNode的大小设置为2n-1,描述节点的数据类型为:typedef struct{int weight; //结点权值int parent;int lchild;int rchild;}HNodeType;2. 求哈夫曼编码时使用一位结构数组HuffCode作为哈腹满编码信息的存储。

求哈夫曼编码,实质上就是在以建立的哈夫曼树中,从叶子结点开始,沿结点的双亲链域退到根结点,每退回一步,就走过了哈夫满树的一个分支,从而得到一位哈夫曼码值,由于一个字符的哈夫曼编码是从根结点到相应叶子结点所经过的路径上各分支所组成的0、1序列,因此先得到的分支代码为所求编码的低位码,后得到的分支代码为所求编码的高位码,所以设计如下数据类型:typedef struct{int bit[26];int start;}HCodeType;3. 文件hfmtree.dat、codefile.dat、和textfile.dat。

数据结构上机实验_树和二叉树的应用_哈夫曼编码设计 (含代码和报告)

数据结构上机实验_树和二叉树的应用_哈夫曼编码设计  (含代码和报告)

数据结构实验报告题目:数据结构实验报告学院:工商管理学院班级:信息1001姓名:彭振宇学号:时间:2012/6/26实验三:树和二叉树的应用一.实验题目:树和二叉树的应用二.实验内容:哈夫曼编码设计三.实验目的:掌握树和二叉树的概念及工作原理,运用其原理及概念完成上述实验题中的内容。

四.实验要求:为了使学生更好的掌握与理解课堂上老师所讲的概念与原理,实验前每个学生要认真预习所做的实验内容及编写源程序伪码(写在纸上及盘中均可)以便在实验课中完成老师所布置的实验内容。

五.概要设计原理:1.选择parent为0且weight最小的两个结点。

其序号分别为s1和s22.建立赫夫曼树叶3.从叶子到根逆向求每个字符的赫夫曼编码4.输出构造的树5.输出得到的各权Huffman编码六.详细程序清单及注释说明:#include<stdio.h>#include<stdlib.h>#include<string.h>#define MAXSIZE 30 //最大叶子数#define MAXCODE 10000 //编码最大长度#define OK 1#define ERROR 0#define OVERLOW -2//=============赫夫曼树和赫夫曼编码的存储表示=====typedef struct{unsigned int weight;unsigned int parent, lchild, rchild;}HTNode,*HuffmanTree; //动态分配数组存储赫夫曼树typedef char **HuffmanCode; //动态分配数组存储赫夫曼编码表/*----------------算法描述----------------*/void Select(HuffmanTree HT, int n, int *s1, int *s2)//选择parent为0且weight最小的两个结点。

哈夫曼树实训报告


4.2 调试结果................................................................................ 19
5、调试经验...................................................................................... 23
}HFMNode,*HFMTree; typedef char **HuffmanCode; HFMTree HT; char str[N+1]; //定义全局变量 HFMTree 指针 //定义全局变量 str 字符数组,存放 53 个字符
//折半查找,用与频率统计、哈夫曼编码 int BinSearch(char str[N+1],int low,int high,char ch) { int mid; if(low<=high) { mid=(low+high)/2; if(ch==str[mid]) return mid; else if(ch<str[mid]) return BinSearch(str,low,mid-1,ch); else
2、系统分析与设计............................................................................ 5
3、算法设计说明................................................................................ 5
-3-
的长度。但是这种编码方式会出现译码的二义性(又称为多义性)。 例如,E 的使用频率较高,对应的译码为 1,D 使用的频率次之,对应的译码为 10,A 使用的频率又次之,对应的译码为 110。假设接到的编码串为“110'’,是翻译成 “ED”,还是“A”呢?这样就产生了译码的二义性。为了避免译码的二义性,人们规 定,对某一字符集进行不等长编码时,任一个字符的编码都不能是其他字符编码的前 缀。在上例中,E 就是 D 和 A 的前缀。 哈夫曼编码就是一种不等长编码,其定义如下。 对于给定的字符集 D={d1,d2,…,dn}及其频率分布 F={wl,w2,…,wn},用 d1, d2,…,dn 作为叶节点,wl,w2,…,wn 作为节点的权,利用哈夫曼算法构造一棵最优二 叉树,将树中每个分支节点的左分支标上“0”,右分支标上“1”,把从根到每个叶子 的路径符号(“0”或“1”)连接起来,作为该叶子的编码。由于哈夫曼树是带权路径长度 最小的树,因此采用这种方法得到的编码长度最小。 哈夫曼编码是在哈夫曼树的基础上求出来的,其基本思想是:从叶子节点 di(0≤i<n)出 发,向上回溯至根节点,依次求出每个字符的编码。 哈夫曼编码的回溯步骤如下: (1) 选出哈夫曼树的某一叶子节点。 (2) 利用其双亲指针 parent 找到其双亲节点。 (3) 利用找到的双亲节点的指针域中的 lchild 和 rchild,判断该节点是双亲的左孩子还是 右孩子。若该节点是其双亲节点的左孩子,则生成代码 0;若该节点是其双亲节 点的右孩子,则生成代码 1。 (4) 由于生成的编码与要求的编码反序,将所生成的编码反序。 (5) 重复步骤(1)~(4),直到所有的节点都回溯完。 在第 4 步中需要将所生成的编码反序,反序的方法是:首先将生成的编码从后向前依 次存放在一个临时的一维数组中,并设一个指针 start 指示编码在该一维数组中的起始位 置。当某个叶子节点的编码完成时,从临时的一维数组的 start 处将编码复制到该字符对 应的 bits 中即可。 哈夫曼树不但可以用来编码,而且还可以用来解码,解码过程正好与编码过程相反。 其解码过程为:从哈夫曼树的根节点出发,依次识别电文中的二进制编码,如果为 0,则 走向左孩子,否则走向其右孩子,走到叶节点时,就可以得到相应的解码字符。 利用哈夫曼编码进行信息通信可以大大提高信道利用率,缩短信息传输时间,降低 传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码;在接收端将 传来的数据进行译码(复原)。对于双工信道(即可以双向传输信息的信道),每端都需要一 个完整的编僻码系统。试为这样的信息收发站写一个哈夫曼码的编译码系统。

哈夫曼编码解码实验报告

哈夫曼编码解码实验1.实验要求掌握二叉树的相关概念掌握构造哈夫曼树,进行哈夫曼编码。

对编码内容通过哈夫曼树进行解码。

2.实验内容通过二叉树构造哈夫曼树,并用哈夫曼树对读取的txt文件进行哈夫曼编码。

编码完成后通过哈夫曼树进行解码。

#include<stdio.h>#include<string.h>#define MAX 100//定义哈夫曼树的存储结构typedef struct{char data;int weight;int parent;int lch;int rch;}HuffNode;//定义哈夫曼编码的存储结构typedef struct{char bit[MAX];int start;}HuffCode;HuffNode ht[2*MAX];HuffCode hcd[MAX];int Coun[127]={0};int n;char s1[200000];char text[5000];//构造哈夫曼树void HuffmanTree(){int i,j,k,left,right,min1,min2;//printf("输入叶子的节点数:");//scanf("%d",&n);printf("字符数量=%d\n",n);for(i=1;i<=2*n-1;i++){ht[i].parent=ht[i].lch=ht[i].rch=0;}j=0;for(i=1;i<=n;i++){/*getchar();printf("输入第%d个叶子节点的值:",i);scanf("%c",&ht[i].data);printf("输入该节点的权值:");scanf("%d",&ht[i].weight);*/for(;j<127;j++){if(Coun[j]!=0){ht[i].data=j;//printf("%c",ht[i].data);ht[i].weight=Coun[j];//printf("%d",ht[i].weight);break;}}j++;}printf("\n");for(i=1;i<=n;i++){printf("%c",ht[i].data);}printf("\n");for(i=n+1;i<=2*n-1;i++){//在前n个结点中选取权值最小的两个结点构成一颗二叉树min1=min2=10000;//为min1和min2设置一个比所有权值都大的值left=right=0;for(k=1;k<=i-1;k++){if(ht[k].parent==0)//若是根结点//令min1和min2为最小的两个权值,left和right 为权值最小的两个结点位置if(ht[k].weight<min1){min2=min1;right=left;min1=ht[k].weight;left=k;}else if (ht[k].weight<min2){min2=ht[k].weight;right=k;}}ht[left].parent=i;ht[right].parent=i;ht[i].weight=ht[left].weight+ht[right].weight;ht[i].lch=left;ht[i].rch =right;}}//构造哈夫曼编码void HuffmanCode(){int i,c,k,f;HuffCode cd;for(i=1;i<=n;i++){cd.start=n;c=i;f=ht[i].parent;while(f!=0){if(ht[f].lch==c)cd.bit[cd.start]='0';elsecd.bit[cd.start]='1';cd.start--;c=f;f=ht[f].parent;}hcd[i]=cd;}printf("输出哈夫曼编码:\n");for(i=1;i<=n;i++){printf("%c:",ht[i].data);for(k=hcd[i].start+1;k<=n;k++)printf("%c",hcd[i].bit[k]);printf("\n");}}//对字母进行编码void Code()//将字符与相应的哈夫曼编码进行匹配,输出编码结果{int i=0,j,k,h=0;while(text[i]!='\0'){for(j=1;j<=n;j++){if(text[i]==ht[j].data){for(k=hcd[j].start+1;k<=n;k++){s1[h]=hcd[j].bit[k];h++;}break;}}i++;}//printf("编码\n");//puts(s1);//printf("\n");}//解码void HuffmanDecode(){printf("解码\n");int len,i,f;char C;//char S[MAXCODE];//scanf("%s",S);//使用gets()直接跳过len=strlen(s1);printf("s1:%d\n",len);f=2*n-1;for(i=0;i<len;i++){if(s1[i]=='0'){f=ht[f].lch;if(ht[f].lch==0&&ht[f].rch==0){C=ht[f].data;printf("%c",C);f=2*n-1;}}else if(s1[i]=='1'){f=ht[f].rch;if(ht[f].lch==0&&ht[f].rch==0){C=ht[f].data;printf("%c",C);f=2*n-1;}}}printf("\n");}//统计字母个数及其权值void Count(){int i,j,m;n=0;i=0;//printf("请仅输入小写字母\n");//例程本省存在一个BUG,只输入一个字母不能进行编码(并未解决)//scanf("%s",s);while(text[i]!='\0')//使用ASCII码表进行统计{m=text[i];//printf("%d\n",m);Coun[m]++;i++;}for(j=0;j<127;j++){if(Coun[j]!=0)n++;}}//mark Codevoid main(){int l=0;FILE *fp;fp=fopen("text.txt","r");if(fp==NULL){printf("文件打开失败\n");while(1);}while(!feof(fp)){text[l] = fgetc(fp);l++;}printf("输入文本\n");printf("%s\n",text);fclose(fp);Count();HuffmanTree();HuffmanCode();Code();HuffmanDecode();}文本文件文本输入进行哈夫曼编码对文本进行编码输出解码结果3.实验总结通过本次实验,对二叉树的应用有了相应的了解,掌握了如何构造哈夫曼编码,如何对编码结果进行解码。

哈夫曼实验报告

一、实验目的1. 理解哈夫曼编码的基本原理和重要性。

2. 掌握哈夫曼树的构建方法。

3. 熟悉哈夫曼编码和译码的实现过程。

4. 分析哈夫曼编码在数据压缩中的应用效果。

二、实验原理哈夫曼编码是一种基于字符频率的编码方法,它利用字符出现的频率来构造一棵最优二叉树(哈夫曼树),并根据该树生成字符的编码。

在哈夫曼树中,频率越高的字符对应的编码越短,频率越低的字符对应的编码越长。

这样,对于出现频率较高的字符,编码后的数据长度更短,从而实现数据压缩。

三、实验内容1. 构建哈夫曼树:- 统计待编码数据中每个字符出现的频率。

- 根据字符频率构建哈夫曼树,其中频率高的字符作为叶子节点,频率低的字符作为内部节点。

- 重复上述步骤,直到树中只剩下一个节点,即为哈夫曼树的根节点。

2. 生成哈夫曼编码:- 从哈夫曼树的根节点开始,对每个节点进行遍历,根据遍历方向(左子树为0,右子树为1)为字符分配编码。

- 将生成的编码存储在编码表中。

3. 编码和译码:- 使用生成的编码表对原始数据进行编码,将编码后的数据存储在文件中。

- 从文件中读取编码后的数据,根据编码表进行译码,恢复原始数据。

四、实验步骤1. 编写代码实现哈夫曼树的构建:- 定义节点结构体,包含字符、频率、左子树、右子树等属性。

- 实现构建哈夫曼树的核心算法,包括节点合并、插入等操作。

2. 实现编码和译码功能:- 根据哈夫曼树生成编码表。

- 编写编码函数,根据编码表对数据进行编码。

- 编写译码函数,根据编码表对数据进行译码。

3. 测试实验效果:- 选择一段文本数据,使用实验代码进行编码和译码。

- 比较编码前后数据的长度,分析哈夫曼编码的压缩效果。

五、实验结果与分析1. 哈夫曼树构建:- 成功构建了哈夫曼树,树中节点按照字符频率从高到低排列。

2. 哈夫曼编码:- 成功生成编码表,字符与编码的对应关系符合哈夫曼编码原理。

3. 编码与译码:- 成功实现编码和译码功能,编码后的数据长度明显缩短,译码结果与原始数据完全一致。

数据结构实验报告(哈夫曼树)

数据结构实验报告实验题目:Huffman编码与解码姓名:学号:院系:实验名称:Huffman编码与解码实验问题描述:本实验需要以菜单形式完成以下功能:1.输入电文串2.统计电文串中各个字符及其出现的次数3.构造哈弗曼树4.进行哈弗曼编码5.将电文翻译成比特流并打印出来6.将比特流还原成电文数据结构的描述:逻辑结构:本实验可用二叉树实现,其逻辑结构为一对二的形式,即一个结点对应两个结点。

在实验过程中我们也应用到了栈的概念。

存储结构:使用结构体来对数据进行存储:typedef struct{int weight;int parent,lc,rc;}HTNode,*HuffmanTree;typedef struct LNode{char *elem;int stacksize;int top;}SqStack;在main函数里面定义一个哈弗曼树并实现上述各种功能。

程序结构的描述:本次实验一共构造了10个函数:1.void HuffTree(HuffmanTree &HT,int n[],int mun);此函数根据给定的mun个权值构建哈弗曼树,n[]用于存放num个权值。

2.void Select(HuffmanTree &HT,int n,int i,int &s1,int &s2);此函数用于在HT[1,i-1]中选择parent为0且weight为最小的两个结点,其下标分别为s1,s2.3.void HuffmanCoding(HuffmanTree HT,char **&HC,int n);此函数从哈弗曼树HT上求得n 个叶子结点的哈弗曼编码并存入数组HC中。

4.void Coding(HuffmanTree HT,char **HC,int root,SqStack &S);此函数用于哈弗曼编码,先序遍历哈弗曼树HT,求得每个叶子结点的编码字符串,存入数组HC,S为一个顺序栈,用来记录遍历路径,root是哈弗曼数组HT中根结点的位置下标。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

一、实验目的和要求 实验目的: 1.熟练掌握通过二叉树的建立来了解二叉树的定义及有关概念,熟悉二叉树的存储结构及性质。 2.熟练哈夫曼树的定义,掌握构造哈夫曼树的方法、哈夫曼编码和译码的方法。 二、实验原理和主要内容

1、实验内容: 1.实现二叉树中所有结点的左、右子树相互交换。 2.利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码。对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编码、译码系统。试为这样的信息收发站写一个哈夫曼码的编码、译码系统。

2、实验原理 1.概要设计 (1)抽象数据类型定义 ADT BinaryTree{ 数据对象:D=D是具有相同特性的数据元素的集合。 数据关系:R=: 若D = 空集,则R =空集,称BinaryTree为空二叉树; 若D ≠空集,则R ={H},H是如下二元关系; (1)在D中存在唯一的称为根的数据元素root,它的关系H下无前驱; (2)若D-{root}≠空集,则存在D-{root}={D1,Dr},且D1∩Dr =空集;; (3)若D1≠空集,则D1中存在唯一的元素x1,属于H,且存在D1上的关系H1属于H;若Dr≠空集,则Dr中存在的唯一的元素Xr,,,H1,Hr}; (4)(D1,{H1})是一颗符合本定义的二叉树,称根的左子树,(Dr,{Hr})是一颗符合本定义的二叉树,称为根的右子树。

基本操作P: InitTree (&T) 操作结果:构造空二叉树T。 BiTreeEmpty(&T) 初始条件:二叉树T已存在。 操作结果:若T为空二叉树,返回TRUE,否则返回FALSE。 InsertChild(T,p,LR,c) 初始条件:二叉树T存在,p指向T中某个结点,LR为0或1,非空二叉树c与T不相交且右子树为空。 操作结果:根据LR为0或1,插入c为T中p所指结点的左或右子树。P所指结点的原有左或右子树则成为c的右子树。 DeleteChild(T,p,LR) 初始条件:二叉树T存在,p指向T中某个结点,LR为0或1. 操作结果:根据LR为0或1,删除T中p所指结点的左或右子树。 PreOrderTraverse(T,Visit()) 初始条件:二叉树T存在,Visit是对结点的操作的应用函数。 操作结果:先序遍历T,对每个结点调用函数Visit一次且仅一次。一旦visit()失败,则操作失败。 InOrderTraverse(T,Visit()) 初始条件:二叉树T存在,Visit是对结点的操作的应用函数。 操作结果:中序遍历T,对每个结点调用函数Visit一次且仅一次。一旦visit()失败,则操作失败。 PostOrderTraverse(T,Visit()) 初始条件:二叉树T存在,Visit是对结点的操作的应用函数。 操作结果:后序遍历T,对每个结点调用函数Visit一次且仅一次。一旦visit()失败,则操作失败。 PreOrderTraverse(T,Visit()) 初始条件:二叉树T存在,Visit是对结点的操作的应用函数。 操作结果:层序遍历T,对每个结点调用函数Visit一次且仅一次。一旦visit()失败,则操作失败。 DestroyBiTree( &T) 初始条件:二叉树T存在。 操作结果:销毁二叉树T。 }ADT BinaryTree

Huffman编码 (1) 根据给定的n个权值{w1,w2,…,wn}构成n棵二叉树的集合F={T1,T2,…,Tn},其中每棵二叉树Ti中只有一个带权值为wi的根节点,其左右子树为空 (2) 在F中选择两棵根结点的权值最小的树作为左右子树构造一棵新的二叉树,且置新的二叉树的根结点的权值为左右子树的权值的和 (3) 在F中删除这里两棵树,同时将新得到的二叉树加入F中, (4) 重复(2)(3),直到F只含有一棵树为止。这棵树就是huffman树。

三、主要仪器设备 操作系统:win7 平台;vc++ 语言;C语言

四、调试分析 通过主函数实现各个函数的功能,查看输出结果。

五、调试结果 1、二叉树的建立与操作 2、哈夫曼码编码器 六、附录 源程序

1、 #include #include #include

#define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define OVERFLOW -2 typedef int Status; typedef char TElemType;

typedef struct BiTNode { TElemType data; struct BiTNode * lchild, *rchild; } BiTNode, *BiTree;

Status InitBiTree (BiTree &T){ T = NULL; return OK; }

Status CreateBiTree(BiTree &T) { char ch; ch=getche();

if (ch == '*') { T = NULL; } else { if (!(T = (BiTNode*) malloc(sizeof(BiTNode)))) exit(OVERFLOW); T->data = ch; CreateBiTree(T->lchild); CreateBiTree(T->rchild); } return OK; }

Status Visit(TElemType e){ printf("%c ",e); return OK; }

Status PreOrderTraverse(BiTree T,Status (*Visit)(TElemType e)){ if(T){ if(Visit(T->data)) if(PreOrderTraverse(T->lchild,Visit)) if(PreOrderTraverse(T->rchild,Visit)) return OK; return ERROR; }else return OK; } Status SwapPrt(BiTree T){ BiTree TempPtr; TempPtr = T->lchild; T->lchild = T->rchild; T->rchild = TempPtr; return OK; }

Status PreOrderSwapPrt(BiTree T,Status (*SwapPrt)(BiTree T)){ if(T){ if(SwapPrt(T)) if(PreOrderSwapPrt(T->lchild,SwapPrt)) if(PreOrderSwapPrt(T->rchild,SwapPrt)) return OK; return ERROR; }else return OK; }

int main() { BiTree T; InitBiTree(T); CreateBiTree(T); printf("\n原来先序遍历输出:"); PreOrderTraverse( T, Visit ); PreOrderSwapPrt( T, SwapPrt ); printf("\n左右指针交换后先序遍历输出:"); PreOrderTraverse( T, Visit ); return 0; }

2 #include #include #include

#define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define OVERFLOW -2 typedef int Status; typedef struct{ int weight; int parent,lchild,rchild; }HTNode,*HuffmanTree;

typedef char ** HuffmanCode; //哈夫曼表

void Select(HuffmanTree &HT, int end, int &min, int &sec){ int i = 1; while(HT[i].parent != 0 ) i++;

int j = i+1; while( HT[j].parent != 0) j++;

int m; if (HT[i].weight < HT[j].weight) { min = i; sec = m = j; } else{ min = j; sec = m = i; }

for (m++ ; m <= end; m++){ if (HT[m].parent != 0) continue; int cur = HT[m].weight; if (cur < HT[min].weight) { sec = min; min = m; } if (HT[min].weight < cur && cur < HT[sec].weight) sec = m; } }

void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int * w, int n){ if(n<=1)return; int m = 2*n-1; HT = ( HuffmanTree ) malloc( ( m+1 ) * sizeof( HTNode ) ); HuffmanTree p = HT+1; for( int i = 1; i <= n; ++i, ++p, ++w){ (*p).weight = *w;

相关文档
最新文档