南邮数据结构上机实验二二叉树的基本操作及哈夫曼编码译码系统的实现
南邮数据结构实验一

实验报告(2014 / 2015 学年第一学期)课程名称数据结构实验名称二叉树基本操作以及哈夫曼编码译码系统实验时间年月日指导单位指导教师学生姓名班级学号学院(系) 专业二叉树的基本运算:一、问题描述1.设计递归算法,实现二叉树的运算:删除一棵二叉树,求一棵二叉树的高度,求一棵二叉树中叶子节点数,复制一棵二叉树,交换一棵二叉树的左右子树2.设计算法,自上而下,自左向右即按层次遍历一棵二叉树3.设计main函数,测试上述每个运算二、系统分析和概要设计首先用maketree构造一棵二叉树,然后遍历二叉树,然后交换每个结点的左右子树,接着算出输得高度和叶子节点,最后删除。
三、详细设计2. 核心算法建立二叉树的void MakeTree(const T& x,BinaryTree<T>& left,BinaryTree<T>& right)和计算叶子节点的int Size();3. 算法分析删除一棵二叉树,求一棵二叉树的高度,求一棵二叉树中叶子节点数,复制一棵二叉树等都是用递归的方法实现。
四、程序代码流程图#include<iostream.h>template<class T>struct BTNode{BTNode(){lChild=rChild=NULL;}BTNode(const T &x){element=x;lChild=rChild=NULL;}BTNode(const T &x,BTNode<T>* l,BTNode<T>* r){element=x;lChild=l;rChild=r;}T element;BTNode<T>* lChild,* rChild;};template<class T>class BinaryTree{public:BinaryTree(){root=NULL;}~BinaryTree(){Clear();}void Copy(BinaryTree<T> &r) const;bool IsEmpty()const{return root == NULL;}void Clear();void Exchange();bool Root(T& x)const;int GetHeight();void MakeTree(const T& x,BinaryTree<T>& left,BinaryTree<T>& right);void BreakTree(T& x,BinaryTree<T>& left,BinaryTree<T>& right);void PreOrder(void (*Visit)(T &x));void LevelOrder(void (*Visit)(T& x));int Size();BinaryTree<T>(BinaryTree<T> &t)root=Copy(t.root);}// void InOrder(void (*Visit)(T &x));// void PostOrder(void (*Visit)(T &x));BTNode<T>* Copy(BTNode<T>* t);protected:BTNode<T> * root;private:static int number;void Clear(BTNode<T>* &t);void Exchange(BTNode<T>* t);int GetHeight(BTNode<T>* t);int Size(BTNode<T>* t);void PreOrder(void (*Visit)(T &x),BTNode<T>* t);void LevelOrder(void (*Visit)(T& x),BTNode<T>* t); // void InOrder(void (*Visit)(T &x),BTNode<T>* t);// void PostOrder(void (*Visit)(T &x),BTNode<T>* t); };template <class T>bool BinaryTree<T>::Root(T &x)const{if(root){x=root->element;return true;}elsereturn false;}template <class T>void BinaryTree<T>::Clear(){Clear(root);}template <class T>void BinaryTree<T>::Clear(BTNode<T>* &t){if(t)Clear(t->lChild);Clear(t->rChild);delete t;t=NULL;}}template <class T>void BinaryTree<T>::MakeTree(const T& x,BinaryTree<T>& left,BinaryTree<T>& right) {if(root||&left==&right)return;root=new BTNode <T>(x,left.root,right.root);left.root=right.root=NULL;}template <class T>void BinaryTree<T>::BreakTree(T& x,BinaryTree<T>& left,BinaryTree<T>& right) {if(!root||&left==&right||left.root||right.root)return;x=root->element;left.root=root->lChild;right.root=root->rChild;delete root;root=NULL;}template <class T>BTNode<T>* BinaryTree<T>::Copy(BTNode<T>* t){if(!t)return NULL;BTNode<T>*q=new BTNode<T>(t->element);q->lChild=Copy(t->lChild);q->rChild=Copy(t->rChild);return q;}template <class T>void Visit(T &x){cout<<x<<" ";}template <class T>void BinaryTree<T>::PreOrder(void (*Visit)(T& x)){PreOrder(Visit,root);}template <class T>void BinaryTree<T>::PreOrder(void (*Visit)(T& x),BTNode<T>* t) {if(t){Visit(t->element);PreOrder(Visit,t->lChild);PreOrder(Visit,t->rChild);}}template <class T>void BinaryTree<T>::Exchange(){Exchange(root);}template <class T>void BinaryTree<T>::Exchange(BTNode<T>* t){if(!t)return;BTNode<T>* temp;temp=t->lChild;t->lChild=t->rChild;t->rChild=temp;Exchange(t->lChild);Exchange(t->rChild);}template <class T>int BinaryTree<T>::GetHeight(){return GetHeight(root);}int BinaryTree<T>::GetHeight(BTNode<T>* t){int templ;int tempr;if(!t)return 0;templ=GetHeight(t->lChild);tempr=GetHeight(t->rChild);if(templ++>tempr++)return templ;elsereturn tempr;}template <class T>int BinaryTree<T>::number=0;template <class T>int BinaryTree<T>::Size(){Size(root);return number;}template <class T>int BinaryTree<T>::Size(BTNode<T>* t){if(t!=NULL){Size(t->lChild);if(t->lChild ==NULL&&t->rChild ==NULL)number++;Size(t->rChild);}return number;}template <class T>void BinaryTree<T>::LevelOrder(void (*Visit)(T& x)) {PreOrder(Visit,root);}void BinaryTree<T>::LevelOrder(void (*Visit)(T& x),BTNode<T>* t) {BTNode *quene[50],*p;int pre=1,rear=1;quene[++pre]=t;while(pre!=0){p=quene[++rear];cout<<p->element<<" ";if(p->lChild !=NULL)quene[++pre]=p->rChild ;if(p->rChild !=NULL)quene[++pre]=p->lChild ;}}void main(){BinaryTree <char> a,b,x,y,z;y.MakeTree('E',a,b);z.MakeTree('F',a,b);x.MakeTree('C',y,z);y.MakeTree('D',a,b);z.MakeTree('B',y,x);cout<<"二叉树z的先序遍历:"<<endl;z.PreOrder(Visit);cout<<endl;cout<<"层次遍历二叉树:";z.LevelOrder(Visit);cout<<endl;BinaryTree<char> q(z);cout<<"复制的二叉树q的先序遍历:"<<endl;q.PreOrder(Visit);cout<<endl;cout<<"树的高度:";cout<<z.GetHeight()<<endl;cout<<"叶子节点数量:";cout<<z.Size()<<endl;z.Exchange();cout<<"二叉树左右子树交换后的先序遍历:"<<endl;z.PreOrder(Visit);cout<<endl;}五、测试用例和运行结果测试用例如main函数中所示,结果如下图所示。
南邮数据结构实验二

实验报告
( 2016 / 2017 学年第一学期)
课程名称数据结构A
实验名称二叉树的基本操作
及哈夫曼编码译码系统的实现
实验时间2017 年 5 月 1 日指导单位计算机学院计算机科学与技术系
指导教师邹志强
学生姓名吴爱天班级学号B15040916 学院(系) 计算机学院专业信息安全
实验报告
之后三步输出,对应的是三种遍历方式,应该输出的测试结果是:
先序:68 69 72 70 74 71 67 75 65 66
中序:72 69 74 70 71 75 67 68 65 66
后序:72 74 75 67 71 70 69 66 65 68
实验结果符合预期。
对于哈夫曼建树操作我自己又按照自己的想法重写了,里面也去学习了C++的字典类MAP,这个类非常好用,可以简单粗暴地提供一些方法和迭代器,让你将关键字和值绑定,这样我每新加入一个字母的数据块,我就可以记录下这对组合,不用之后搜索和解码的时
之后进行编码,其实也是一个搜索的过程,主要是调用了一个
测试:。
数据结构哈夫曼树编码及译码的实现实验报告

实验:哈夫曼树编码及译码的实现一.实验题目给定字符集的HUFFMANN编码与解码,这里的字符集及其字符频数自己定义,要求输出个字符集的哈夫曼编码及给定的字符串的哈夫曼码及译码结果。
二.实验原理首先规定构建哈夫曼树,然后进行哈夫曼树的编码,接着设计函数进行字符串的编码过程,最后进行哈夫曼编码的译码。
首先定义一个结构体,这个结构体定义时尽可能的大,用来存放左右的变量,再定义一个地址空间,用于存放数组,数组中每个元素为之前定义的结构体。
输入n个字符及其权值。
构建哈夫曼树:在上述存储结构上实现的哈夫曼算法可大致描述为:1.首先将地址空间初始化,将ht[0…n-1]中所有的结点里的指针都设置为空,并且将权值设置为0.2.输入:读入n个叶子的权值存于向量的前n个分量中。
它们是初始森林中n个孤立的根结点上的权值。
3.合并:对森林中的树共进行n-1次合并,所产生的新结点依次放入向量ht的第i个分量中。
每次合并分两步:①在当前森林ht[0…i-1]的所有结点中,选取权最小和次小的两个根结点[s1]和 [s2]作为合并对象,这里0≤s1,s2≤i-1。
②将根为ht[s1]和ht[s2]的两棵树作为左右子树合并为一棵新的树,新树的根是新结点ht[i]。
具体操作:将ht[s1]和ht[s2]的parent置为i,将ht[i]的lchild和rchild分别置为s1和s2 .新结点ht[i]的权值置为ht[s1]和ht[s2]的权值之和。
4.哈夫曼的编码:约定左子为0,右子为1,则可以从根结点到叶子结点的路径上的字符组成的字符串作为该叶子结点的编码。
当用户输入字母时。
就在已经找好编码的编码结构体中去查找该字母。
查到该字母就打印所存的哈夫曼编码。
接着就是完成用户输入0、1代码时把代码转成字母的功能。
这是从树的头结点向下查找,如果当前用户输入的0、1串中是0则就走向该结点的左子。
如果是1这就走向该结点的右结点,重复上面步骤。
二叉树基本操作与哈夫曼编码译码系统实现

{
return h1+1;
}
else
{
return h2+1;
}
}
求一棵二叉树中叶子结点的个数:
思路:递归搜索二叉树的叶子结点,不断累加。
代码:
template<class T>
int BinaryTree<T>::Leaves()
{
int number=0;
Leaf(root,number);
BTNode<T>* Copy(BTNode<T> *t);
void Change(BTNode<T> *t);
};
template<class T>
bool BinaryTree<T>::Root(T &x)const
{
if(root==0)
{
cout<<"This tree is empty!"<<endl;
return ;
}
BTNode<T> *p=root;
BTNode<T> t;
SeqQueue< BTNode<T> > q(30);
q.EnQueue(*p);
while(!q.IsEmpty())
{
q.Front(t);
};
template<class T>
class BinaryTree
{
public:
BinaryTree(){root=NULL;}
~BinaryTree();
bool IsEmpty()const;//判断二叉树是否为空
实验报告2_二叉树及哈夫曼编码

实验报告
(2013/ 2014 学年第二学期)
课程名称数据结构A
实验名称实验二二叉树的基本操作及哈夫曼编码译码系统的实现
实验时间2014 年 4 月8 日
指导单位计算机学院计算机软件教学中心
指导教师朱立华
学生姓名高怡馨班级学号B12140113
专业教育技术学
学院(系) 教育科学与技
术学院
实验报告
七.求二叉树的深度:
A.自然语言描述:
1:判断根节点是否为空,如果根节点为空,返回0
2:如果根节点不为空但是根节点的左右孩子同时为空,返回1
3:如果以上两个条件都不成立
4:递归调用求二叉树的深度,函数的参数改为根节点的左孩子,并且深度初始化为1 5:递归调用求二叉树的深度,函数的参数改为跟结点的右孩子,并且深度初始化为0 6:返回4与5步中得出深度较大的那个数作为二叉树的深度数
B.代码详细分析:
template <class T>
int BinaryTree<T>::GetHeight(BTNode<T>* t)
{
int templ;
int tempr;
if(!t)
return 0;
templ=GetHeight(t->lChild);
tempr=GetHeight(t->rChild);
if(templ++>tempr++)
return templ;
else
return tempr;
}
测试结果。
二叉树验证实验和哈夫曼编码的代码

实验六二叉树构造和遍历一. 实验目的⑴掌握二叉树的逻辑结构;⑵掌握二叉树的二叉链表存储结构;⑶掌握基于二叉链表存储的二叉树的遍历操作的实现。
二. 实验环境Windows操作系统,Visual C++ 6.0编程环境。
三. 实验内容和步骤1.观察下面图6-1的二叉树,回答问题。
图6-1(1)写出前序、中序和后序遍历序列;前序:ABDECFG 中序:DBEAFGC 后序:DEBGFCA (2)分别写单支结点和叶子结点;单支结点:CF 叶子结点:DEG(3)以”#”补充所有结点的空分支;ABD##E##CF#G###(4)写出补充空分支后二叉树的前序遍历序列(扩展的前序遍历序列);ABD##E##CF#G###2.建立工程Bitree,编写Biree.h,Biree.cpp和测试函数Bireemain.cpp,完成下列功能。
⑴建立一棵含有n个结点的二叉树,采用二叉链表存储;⑵前序(或中序、后序)遍历该二叉树。
四.编码头文件Bitree.h#include<iostream>using namespace std;template <class T>struct BiNode{T data;BiNode<T> *lchild, *rchild;};template <class T>class BiTree{public:BiTree(){root=Creat(root);} //有参构造函数,初始化一棵二叉树,其前序序列由键盘输入~BiTree(){Release(root);} //析构函数,释放二叉链表中各结点的存储空间void PreOrder(){PreOrder(root);} //前序遍历二叉树void InOrder(){InOrder(root);} //中序遍历二叉树void PostOrder(){PostOrder(root);} //后序遍历二叉树private:BiNode<T> *root; //指向根结点的头指针BiNode<T> *Creat(BiNode<T> *bt); //有参构造函数调用void Release(BiNode<T> *bt); //析构函数调用void PreOrder(BiNode<T> *bt);void InOrder(BiNode<T> *bt);void PostOrder(BiNode<T> *bt);};template <class T>BiNode<T> *BiTree<T>::Creat(BiNode<T> *bt){T ch;cin>>ch;if(ch=='#')bt=NULL; //建立一棵空树else {bt=new BiNode<T>; //生成一个结点bt->data=ch;bt->lchild=Creat(bt->lchild); //递归建立左子树bt->rchild=Creat(bt->rchild); //递归建立右子树}return bt;}template <class T>void BiTree<T>::Release(BiNode<T> *bt){if(bt!=NULL){Release(bt->lchild);Release(bt->rchild);delete bt;}}template <class T>void BiTree<T>::PreOrder(BiNode<T> *bt){if (bt==NULL) return; //递归调用的结束条件else {cout<<bt->data; //访问根结点的数据域PreOrder(bt->lchild); //前序递归遍历root的左子树PreOrder(bt->rchild); //前序递归遍历root的右子树}}template <class T>void BiTree<T>::InOrder(BiNode<T> *bt){if (bt==NULL) return; //递归调用的结束条件else {InOrder(bt->lchild);cout<<bt->data;InOrder(bt->rchild);}}template <class T>void BiTree<T>::PostOrder(BiNode<T> *bt){if (bt==NULL) return; //递归调用的结束条件else {PostOrder(bt->lchild);PostOrder(bt->rchild);cout<<bt->data;}}主函数main#include"Bitree.h"void main(){int c=1;while(c){cout<<"输入前序序列:";BiTree<char> tree;cout<<"前序遍历:";tree.PreOrder();cout<<endl;cout<<"中序遍历:";tree.InOrder();cout<<endl;cout<<"后序遍历:";tree.PostOrder();cout<<endl;cout<<"0.结束 1.重试"<<endl;cout<<"请选择:";cin>>c;}}五.调试结果(表5-1)(表5-1)二叉树验证实验调试结果六.实验小结本次实验主要是通过实验过程掌握二叉树的逻辑结构,掌握二叉树的二叉链表存储结构和掌握基于二叉链表存储的二叉树的遍历操作的实现。
数据结构实验二哈夫曼树及哈夫曼编码译码的实现
福建农林大学金山学院实验报告系(教研室):专业:计算机科学与技术年级:08 实验课程:姓名:学号:实验室号:_______ 计算机号:实验时间:指导教师签字:成绩:实验二:哈夫曼树及哈夫曼编码译码的实现(验证性、4学时)一、实验目的和要求构建哈夫曼树及哈夫曼编码,输出哈夫曼树及哈夫曼编码,完成编码与译码的算法。
(1)掌握树的有关操作算法(2)熟悉树的基本存储方法(3)学习利用树求解实际问题二、实验内容和原理定义哈夫曼树的存储结构;输入要编码的字符权重,根据权重建立哈夫曼树,并进行编码,最后输出哈夫曼编码。
三、实验环境硬件:(1)学生用微机(2)多媒体教室或远程教学(3)局域网环境软件:(1)Windows XP中文操作系统(2)Turbo C 3.0四、算法描述及实验步骤1.算法描述(1).建立哈夫曼树的算法定义各节点类型其中应包含两类数据一是权重域weight;一是指针域而指针域中应该包括指向左右孩子和指向双亲的指针这里分别用lchild、rdhild和parent来表示因此可用静态三叉链表来实现,在实际构造中由于是叶子节点来构造新的根节点其构造过程中仅与叶子节点的权重有关而与其数据域无关所以构造过程中不用考虑其数值域,并且在链表中从叶子开始存放,让后不断的将两颗最小权值的子树合并为一颗权值为其和的较大的子树,逐步生成各自内部节点直到树根。
(2).哈夫曼编码的算法将建立的哈夫曼树从每个叶子节点开始沿着双亲域回到根节点,梅走一步进行编码得到一位编码值;由于每个叶子节点的哈夫曼编码是从根节点到相应的叶子的路径的各个分支的代码组成的0和1序列,所以先得到了低位编码后得到高位编码因此可用一维数组从后向前来存放各位编码值,并用start来记录编码的起始位置。
2.算法流程图构建哈夫曼树算法流程哈夫曼编码算法流程3.代码仅作参考--redbatzero#include <stdio.h>#include <malloc.h>#define maxvalue 10000 //定义最大权值常量#define maxnodenumber 100 //定义节点最大数#define maxbit 10 //定义哈弗曼编码最大长度typedef struct //定义新数据类型即节点结构{int weight; //权重域int parent,lchild,rchild; //指针域}htnode; //节点类型标识符//typedef htnode * huffmanstree; //定义哈弗曼数类型htnode ht[maxnodenumber]; //定义三叉链表存储数组typedef struct //定义保存一个叶子节点哈弗曼编码的结构{int bit[maxbit]; //定义一维数组为编码域int start; //定义位置域}hcnodetype; //定义编码类型htnode * creatstree(int n) //huffmanstree creatstree(int n) //建立哈夫曼树算法实现函数{int i,j,m1,m2,k1,k2; //局部变量for(i=0;i<2*n-1;i++) //初始化各节点{ht[i].weight=0; //权重初始化为0ht[i].parent=-1; //根节点和给左右孩子初始化为-1ht[i].lchild=-1;ht[i].rchild=-1;}for(i=0;i<n;i++) //权重赋初值,由用户输入{scanf("%d",&ht[i].weight);}for(i=0;i<n-1;i++) //生成新节点构造哈夫曼树{m1=maxvalue; //预置最小权值变量为最大权值m2=maxvalue; //预置次小权值变量为最大权值k1=0; //预置最小权值节点位置为下标为0处k2=0; //预置次小权值节点位置为下标为0处for(j=0;j<n+i;j++) //循环找出每趟最下权值和所在位置if(ht[j].parent==-1&&ht[j].weight<m1){m2=m1;k2=k1;m1=ht[j].weight;k1=j;}else //当小于当前次小m2则更新m2及其位置if(ht[j].parent==-1&&ht[j].weight<m2){m2=ht[j].weight;k2=j;}ht[k1].parent=n+i; //修改最小权值节点的双亲为刚生成的新节点ht[k2].parent=n+i; //修改次小权值节点的双亲为刚生成的新节点ht[n+i].weight=ht[k1].weight+ht[k2].weight; //将新生成的权重值填入新的根节点ht[n+i].lchild=k1; //新生节点左孩子指向k1ht[n+i].rchild=k2; //新生节点右孩子指向k2}return ht; //返回哈夫曼树指针}void getstree(htnode * ht,int n) //哈夫曼编码算法及打印函数的实现{int i,j,c,p; //局部变量的定义hcnodetype cd[maxnodenumber]; //定义存储哈夫曼编码的数组for(i=0;i<n;i++) //循环控制对每一个节点进行编码{c=i; //为编码各节点初始化c和jj=maxbit;do{j--; //j指向bit中存放编码为的正确位置p=ht[c].parent; //p指向c的双亲节点if(ht[p].lchild==c) //如果c是p的左孩子cd[i].bit[j]=0; //编码为赋值0else //否则即c是p的右孩子cd[i].bit[j]=1; //编码赋值1c=p;//更新当前指针,为下一节点编码做准备}while(ht[p].parent!=-1); //判断是否编码结束即循环至最终根节点cd[i].start=j; //编码完成,记下编码开始位置}for(i=0;i<n;i++) //循环打印各节点哈夫曼编码{for(j=cd[i].start;j<maxbit;j++)//循环逐一输出printf("%d",cd[i].bit[j]);printf("\n"); //每输出一编码后换行}}int main() //主函数{int n;printf("请输入节点数:"); //用户输入节点数scanf("%d",&n);htnode * p; // huffmanstree p //定义哈夫曼树类型pp=(htnode * )malloc(sizeof(htnode *));//p=(huffmanstree)malloc(sizeof(huffmanstree))//分配内存空间p=creatstree(n);//调用建立哈夫曼树函数赋返回值给pgetstree(p,n); //调用编码函数读入建立的哈夫曼树p进行编码return 0;}五、调试过程出现该错误是因为type识别不了,即定义哈夫曼树时确切的说是type并不能定义htnode *标识符为huffmanstree:type htnode * huffmanstree这个小错误可以通过连个方法来修改一是将type改为typedef,当然直接删除该定义完全不会影响程序的执行,但在定义建立哈夫曼树函数时返回值应直接用htnode *;该错原因是参数未能成功传递,其中的ht[p]系统当做是未定义的类型可知,在getstree(htnode ht,int n)时正确的应当是传递哈夫曼树的头指针即数组首地址ht因此改为getstree(htnode * ht,int n)六、实验结果通过改正后成功编译连接,进行数据测试{5,20,12,7,47,9}当然编码因为定义时大小的左右排序是不同的所以编码也不唯一,但在这里是以左小右大来分布的,所以编码结果符合预期的。
实验2二 叉 树 的基本操作及哈夫曼编码 (1)
实验内容
• • • • • • • • • 1 输入字符序列,建立二叉链表。 2 按先序、中序和后序遍历二叉树(递归算法)。 3 按某种形式输出整棵二叉树。 4 求二叉树的高度。 5 求二叉树的叶节点个数。 6 交换二叉树的左右子树。 7 借助队列实现二叉树的层次遍历。 8 哈夫曼编码的实现(选作) 9 在主函数中设计一个简单的菜单,分别调试上 述算法。
• • • • • • • • • • • • • • • • • • • • • • • •
运行结果: ===================主菜单=================== 1.建立二叉树方法1 2.建立二叉树方法2 3.先序递归遍历二叉树 4.中序递归遍历二叉树 5.后序递归遍历二叉树 6.层次遍历二叉树 7.计算二叉树的高度 8.计算二叉树中叶结点个数 9.交换二叉树的左右子树 10.打印二叉树 0.结束程序运行 ============================================ 请输入您的选择(0,1,2,3,4,5,6,7,8,9,10) 1 请输入二叉树各结点的编号和对应的值(如1,a):1,a 请继续输入二叉树各结点的编号和对应的值:2,b 请继续输入二叉树各结点的编号和对应的值:3,c 请继续输入二叉树各结点的编号和对应的值:4,d 请继续输入二叉树各结点的编号和对应的值:6,e 请继续输入二叉树各结点的编号和对应的值:7,f 请继续输入二叉树各结点的编号和对应的值:9,g 请继续输入二叉树各结点的编号和对应的值:13,h 请继续输入二叉树各结点的编号和对应的值:0,#
• case 8:if(t) • {printf("二叉树的叶子结点数为:%d\n",leafcount(t)); • printf("二叉树的叶结点为:");paintleaf(t); • printf("\n"); • } • else printf("二叉树为空!\n"); • break; case 9:if(t) • {printf("交换二叉树的左右子树:\n"); • exchange(t); • prtbtree(t,0); • printf("\n"); • } • else printf("二叉树为空!\n"); • break; •
数据结构实验,哈夫曼编码译码系统
数据结构实验,哈夫曼编码译码系统展开全文1. 实验名称: 二叉树的基本操作及哈夫曼编码译码系统的实现2.实验目的:创建一棵二叉树,实现先序、中序和后序遍历一棵二叉树,计算二叉树结点个数等操作。
哈夫曼编码/译码系统。
3. 实验任务:能成功演示二叉树的有关运算,运算完毕后能成功释放二叉树所有结点占用的系统内存。
4. 实验内容(1)在二叉链表上实现二叉树运算a) 设计递归算法,实现二叉树的基本运算:删除一棵二叉树,求一棵二叉树的高度,求一棵二叉树中叶子结点数,复制一棵二叉树,交换一棵二叉树的左右子树。
b) 设计算法,按自上到下,自左到右的次序,即按层次遍历一棵二叉树。
c) 设计main函数,测试上述每个运算。
d) 提示:队列结构可以辅助进行层次遍历,队列的元素类型是指向二叉树结点的指针类型。
(2)哈夫曼编码和译码系统a) 设计一个菜单可以循环显示B——建树:读入字符集和各字符频度,建立哈夫曼树。
T——遍历:先序和中序遍历二叉树。
E——生成编码:产生每个字符的哈夫曼编码。
C——编码:输入由字符集中字符组成的任意字符串,利用已经生成的哈夫曼编码进行编码,显示编码结果。
D——译码:利用已建成的哈夫曼树进行译码。
X——退出。
b) 提示:修改二叉树结点类BTNode,增加一个指向双亲的parent域,修改二叉树类的函数MakeTree设置该域的值;可以通过遍历哈夫曼树生成每个叶子结点的哈夫曼编码。
5. 概要设计1) 二叉树首先定义结点类BTNode包括对结点的访问,打印,交换结点左右元素等操作。
并将二叉树类BTree声明为友元类。
二叉树类中包含了建树,判断二叉树是否为空,求结点数,求高度,删除,交换左右子树,三种次序遍历及按层次遍历,清空二叉树等函数。
在主函数中调用实现这些功能。
类和类的层次设计主要算法:PreOrder:输出当前结点元素,左右孩子递归调用函数。
InOrder:左孩子递归调用函数,输出当前结点元素,右孩子递归调用。
南邮数据结构实验报告
南邮数据结构实验报告实验目的,通过本次实验,我们旨在加深对数据结构的理解,掌握数据结构的基本操作和算法设计能力,提高对数据结构的应用能力和实际问题的解决能力。
一、实验内容。
1. 实验一,线性表的基本操作。
本次实验中,我们首先学习了线性表的基本概念和操作,包括插入、删除、查找等操作,并通过实际编程操作来加深对线性表的理解。
2. 实验二,栈和队列的应用。
在实验二中,我们通过实际编程操作来学习栈和队列的应用,包括中缀表达式转换为后缀表达式、栈的应用、队列的应用等内容。
3. 实验三,树和二叉树的基本操作。
实验三中,我们学习了树和二叉树的基本概念和操作,包括树的遍历、二叉树的建立和遍历等内容,并通过实际编程操作来加深对树和二叉树的理解。
4. 实验四,图的基本操作。
最后,我们学习了图的基本概念和操作,包括图的存储结构、图的遍历等内容,并通过实际编程操作来加深对图的理解。
二、实验过程。
在实验过程中,我们首先对实验内容进行了深入的学习和理解,掌握了数据结构的基本概念和操作方法。
然后,我们通过实际编程操作来加深对数据结构的理解,并通过调试和修改程序来提高对数据结构的应用能力和实际问题的解决能力。
在实验过程中,我们遇到了一些问题,但通过不懈的努力和团队合作,最终顺利完成了实验任务。
三、实验结果与分析。
通过本次实验,我们深入理解了数据结构的基本概念和操作方法,掌握了线性表、栈、队列、树、二叉树和图的基本操作,并通过实际编程操作加深了对数据结构的理解。
同时,我们也提高了对数据结构的应用能力和实际问题的解决能力,为今后的学习和工作打下了坚实的基础。
四、实验总结。
通过本次实验,我们不仅加深了对数据结构的理解,还提高了对数据结构的应用能力和实际问题的解决能力。
在今后的学习和工作中,我们将继续努力,不断提升自己的专业能力,为将来的发展打下坚实的基础。
以上就是本次实验的报告内容,谢谢!。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验报告(2015 / 2016学年第二学期)课程名称数据结构A实验名称二叉树的基本操作及哈夫曼编码译码系统的实现实验时间2016 年 4 月14 日指导单位计算机科学与技术系指导教师骆健学生姓名班级学号学院(系) 管理学院专业信息管理与信息系统实习题名:二叉树的基本操作班级姓名学号日期2016.04.14一、问题描述设计递归算法,实现下列二叉树运算:删除一棵二叉树、求一棵二叉树的高度、求一棵二叉树中叶子结点数、复制一棵二叉树、交换一棵二叉树的左右子树。
设计算法,按自上到下,从左到右的顺序,按层次遍历一棵二叉树。
设计main函数,测试上述每个运算。
二、概要设计文件tree.cpp中在该文件中定义二叉树的链式存储结构,用队列实现二叉树的层次遍历,并且编写实现二叉树的各种基本操作函数。
其中包括结点类BTNode,循环队列类SeqQueue,二叉树类BinaryTree。
主函数main的代码如图所示。
三、详细设计1.类和类的层次设计程序定义了循环队列SeqQueue类和二叉树BinaryTree类。
SeqQueue类主要是用队列实现,层次遍历。
运用后序遍历思想,把树分解为左右子树和跟结点再进行左右交换并计算树的高度,最后删除二叉树。
(b)二叉树类2.核心算法程序利用循环队列SeqQueue类通过不断出队并输出节点的值,将左右孩子入队直到队列为空实现二叉树的层次遍历。
并运用后序遍历思想,将二叉树树分解为左右子树和根结点,利用(p -> lChild)和(p -> rChild)计算结点数目,并通过交换结点的左右子树实现左右交换,计算树的高度,最后删除二叉树。
核心算法主要是二叉树BinaryTree类中的High,Node_num,Exchange,Level_traversal四个函数,其设计流程图如下:High()Node_num()Exchange()Level_traversal()四、程序代码template<class T>int BinaryTree<T>::Node_num(BTNode<T>*p) //叶子结点{if(p){if(p -> lChild == NULL && p -> rChild == NULL)return 1;elsereturn Node_num(p -> lChild) + Node_num(p -> rChild);}elsereturn 0;}template<class T>void BinaryTree<T>::Exchange(BTNode<T>*&t) //左右子树交换{if(t){BTNode<T>*q = t -> lChild;t -> lChild = t->rChild;t -> rChild = q;Exchange(t -> lChild);Exchange(t -> rChild);}}template<class T>void BinaryTree<T>::Level_traversal(void(*Visit)(T&x)) //层次遍历{Level_traversal(Visit, root);cout << endl;}template<class T>void BinaryTree<T>::Level_traversal(void(*Visit)(T&x),BTNode<T>*t) //层次遍历{BTNode<T> *a;Visit(t -> element);if(t -> lChild)s.EnQueue(t -> lChild);if(t -> rChild)s.EnQueue(t -> rChild);while(s.Front(a) == true){if(a -> lChild)s.EnQueue(a -> lChild);if(a -> rChild)s.EnQueue(a -> rChild);Visit(a -> element);s.DeQueue();}}五、测试和调试1.测试用例和结果测试结果如下图2.结果分析1)程序能够正确的实现二叉树的基本的建立、删除、复制、遍历以及结点计算等基本操作。
2)由测试结果来看,可以在输出数据时以二叉树图形的形式输出,更简单直观,因此程序还有待改进。
实习题名:哈夫曼编码和译码系统班级姓名学号日期2016.04.14一、问题描述所设计的系统重复显示以下菜单项:B―――建树:读入字符集和各字符频度,建立哈夫曼树。
T―――遍历:先序和中序遍历二叉树。
E―――生成编码:根据已建成的哈夫曼树,产生各字符的哈夫曼编码。
C―――编码:输入由字符集中字符组成的任意字符串,利用已生成的哈夫曼编码进行编码,显示编码结果,并将输入的字符串及其编码结果分别保存在磁盘文件textfile.txt和codefile.txt中。
D―――译码:读入codefile.txt,利用已建成的哈夫曼树进行译码,并将译码结果存入磁盘文件result.txt中。
P―――打印:屏幕显示文件textfile.txt、codefile.txt和result.txt。
X―――退出。
二、概要设计文件Huffman.cpp中定义了四个类,分别是优先权队列类PrioQueue和结点类BTNode、二叉树类BinaryTree以及哈夫曼树类HfmTree,其中哈夫曼树类HfmTree 继承了二叉树类BinaryTree。
主函数mian的代码如图所示:三、详细设计1.类和类的层次结构程序定义了优先权队列类PrioQueue存储元素,为便于实哈夫曼树的建树运算,定义了哈夫曼树类HfmTree是二叉树类BinaryTree的派生类,新增私有的数据成员weight保存二叉树根的权值。
成员函数getW和putW用于存取该值。
2.核心算法定义了类之后,通过函数Make_Ht建树,将相应的字符和权值录入。
通过遍历哈夫曼树,产生每个叶子节点的哈夫曼编码,当遍历访问某个叶节点是,从该结点到根的路径可以确定该叶结点所代表的字符的编码。
实现译码时,首先将字符读入一维数组,根据0或1向左走向右走直到叶子结点,并将结果写入文件中。
其中关键函数编码code和译码Compile以及打印Print的流程图如下。
code()下接下一页CompilePrint()四、程序代码HfmTree<int> Ht;int num;void Make_Ht(){char str[100];int weight[100];cout << "请输入字符个数:";cin >> num; //建树cout << "请输入权值:";for(int i = 0; i < num; i++)cin >> weight[i];cout << "请输入相应字符集:";cin >> str;Ht = CreateHfmTree(weight, str, num);}void Traversal_Ht(){Ht.PreOrder(Visit);Ht.InOrder(Visit);}template<class T>void BinaryTree<T>::Create_code(){Create_code(root);}template<class T>void BinaryTree<T>::Create_code(BTNode<T>*t){if(t){if(t -> parent){for(int j = 0; j <= i; j++)t -> z[j] = t -> parent -> z[j]; //复制双亲的编码域i++;t -> z[i] = t-> val; //在编码域中加入自己的编码}Create_code(t -> lChild); //递归,先左孩子,再右孩子Create_code(t -> rChild);i--;}}template<class T>void BinaryTree<T>::Create_code_out() //生成编码并输出{Create_code_out(root);}template<class T>void BinaryTree<T>::Create_code_out(BTNode<T>*t){if(t){if(t -> lChild == t -> rChild) //叶子结点{cout << t -> ch << ":"; //输出叶子结点中的字符int i = 0;while(t -> z[i] != -1){cout << t -> z[i]; //输出编码域i++;}cout << endl;}Create_code_out(t->lChild);Create_code_out(t->rChild);}}template<class T>void BinaryTree<T>::Code(){Code(root);}template<class T>void BinaryTree<T>::Code(BTNode<T>*t) //编码{ofstream outf("textfile.txt");if(!outf){cout << "Cannot open the file\n";return;}ofstream outs("codefile.txt",ios::trunc);if(!outs){cout << "Cannot open the file\n";return;}outs.close();char str2[100];cout << "请输入由字符集中字符组成的任意字符串: "; cin >> str2;outf << str2;outf.close();int l = strlen(str2);cout << "编码为:" << endl;for(int i = 0; i < l; i++)Make(root, str2[i]);cout << endl;}template<class T>void BinaryTree<T>::Make(BTNode<T> *t,char a){int i = 0;if(t){if(t -> ch == a) //找到相应字符{ofstream outs("codefile.txt",ios::app);while(t -> z[i] != -1){cout << t -> z[i]; //输出编码域outs << t -> z[i]; //将编码写入文件i++;}outs.close();return;}Make(t -> lChild, a);Make(t -> rChild, a);}}template<class T>void BinaryTree<T>::Compile() //译码{Compile(root);}template<class T>void BinaryTree<T>::Compile(BTNode<T> *t){ifstream inf("codefile.txt");if(!inf){cout << "Cannot open the file\n";return;}ofstream outs("result.txt",ios::trunc);if(!outs){cout << "Cannot open the file\n";return;}outs.close();char *re;char tmp;int n = 0;while(inf.get(tmp) != '\0'){n++; //确定字符数量}inf.close();re = new char[n+1];int n2 = 0;ifstream in("codefile.txt");if(!in){cout<<"Cannot open the file\n";return;}while(in.get(tmp) != '\0'){re[n2] = tmp; //将字符读入一位数组n2++;}BTNode<T> *c;cout << "译码为:";int n3 = 0;while(n3 < n){while(t){c = t;if(re[n3] == '0') //左0右1根据0或1向左走向右走直到叶子结点t = t -> lChild;elset = t -> rChild;n3++;}ofstream outs("result.txt",ios::app);if(!outs){cout << "Cannot open the file\n";return;}cout << c -> ch; //输出字符outs << c -> ch; //将结果写进文件outs.close();t = root;n3--;}cout << endl;}void Print(){char str;ifstream a("textfile.txt");ifstream b("codefile.txt");ifstream c("result.txt");if(!a){cout << "Cannot open the file\n";return;}if(!b){cout << "Cannot open the file\n";return;}if(!c){cout << "Cannot open the file\n";return;}cout << "textfile.txt内的内容为:";while(a.get(str) != '\0')cout << str;cout << endl;cout << "codefile.txt内的内容为:";while(b.get(str) != '\0')cout << str;cout << endl;cout << "result.txt内的内容为:";while(c.get(str) != '\0')cout << str;cout << endl;a.close();b.close();c.close();}五、测试和调试1.测试用例和结果1)输入B选择建树操作2)分别输入a,b,c,d以及权值2,4,1,1,建树3)输入T得到该树的遍历4)输入E生成编码5)输入C编码,输入字符串aabdcbdacbdadcdb6)输入D选择译码7)输入P选择打印文件内容8)最后输入X退出2.结果分析1)程序能够完全实现题目的要求,建树,遍历生成编码,编码以及译码打印都能成功完成2)不足之处在于译码方面,不能够实现自己输入一串编码来实现译码,下一步的目标是解决这个问题实习小结通过这次课程设计,使我对二叉树的相关知识有了更深的理解,我们要根据不同的需求,采用不同的数据存储方式,不一定要用栈,二叉树等高级类型,有时用基本的一维数组,只要运用得当,也能达到相同的效果,甚至更好。