北京邮电大学数据结构实验报告与源代码实验三二叉树

合集下载

实验三 二叉树

实验三  二叉树

实验三二叉树
一、实验目的
1.掌握二叉树的链式存储结构及其相关操作的实现。

2.掌握二叉树的先序、中序、后序的递归遍历算法。

3.理解二叉树的各种非递归遍历算法的实现。

二、实验要求
1.实验前做好充分准备,包括复习第六章所学内容,事先预习好本次实验内容。

2.实验时记录实验结果,按要求完成各题。

3.实验结束后,给出实验总结与分析并及时给出本次实验的实验报告。

三、实验题目
本次实验给出的选定题目如下表所示。

说明:
(1)实验内容1)为必做内容。

(2)实验内容2)与实验内容3)为选做内容。

四、实验内容与要求
1、实验题目一:(1)二叉树的创建、递归遍历及其它基本操作的实现。

要求:定义用二叉链表表示的二叉树,并实现二叉树的创建、遍历(先序、中序后序)的递归算法及求深度操作等,并对其进行验证。

2、实验题目二:二叉树非递归遍历算法的实现
要求:在题目一的基础上,实现二叉树的非递归遍历算法(先序、中序、后序或按层),并对其进行验证。

3、实验题目三:哈夫曼树及哈夫曼编码的算法实现
要求:编程实现哈夫曼树的创建及利用哈夫曼树求解哈夫曼编码。

北邮数据结构实验报告

北邮数据结构实验报告

北邮数据结构实验报告北京邮电大学信息与通信工程学院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。

北邮数据结构平衡二叉树报告概论

北邮数据结构平衡二叉树报告概论

数据结构实验报告实验名称:平衡二叉树1.实验目的和内容根据平衡二叉树的抽象数据类型的定义,使用二叉链表实现一个平衡二叉树。

二叉树的基本功能:1、平衡二叉树的建立2、平衡二叉树的查找3、平衡二叉树的插入4、平衡二叉树的删除5、平衡二叉树的销毁6、其他:自定义操作编写测试main()函数测试平衡二叉树的正确性。

2. 程序分析2.1 存储结构struct node{int key; //值int height; //这个结点的父节点在这枝最长路径上的结点个数node *left; //左孩子指针node *right; //右孩子指针node(int k){ key = k; left = right = 0; height = 1; } //构造函数};2.2 程序流程2.3 关键算法分析(由于函数过多,在此只挑选部分重要函数)算法1:void AVL_Tree::left_rotate(node *&x)[1] 算法功能:对 R-R型进行调整[2] 算法基本思想:将结点右孩子进行逆时针旋转[3] 算法空间、时间复杂度分析:都为0(1)[4] 代码逻辑node *y = x->right; y为x的右孩子x->right = y->left; 将y的左孩子赋给x的右孩子 y->left = x; x变为y的左孩子fixheight(x); 修正x,y的height值fixheight(y);x = y; 使x的父节点指向y 算法2:void A VL_Tree::right_rotate(node *&x)[1] 算法功能:对L-L型进行调整[2] 算法基本思想:将左孩子进行顺时针旋转[3] 算法空间、时间复杂度分析:都为0(1)[4] 代码逻辑node *y = x->left; //y为x的左孩子 x->left = y->right; y的右孩子赋给x的左孩子y->right = x; x变为y的右孩子fixheight(x); 修正x和y的height值fixheight(y);x = y; 使x的父节点指向y算法3:node*& A VL_Tree::balance(node *&p)[1] 算法功能:对给定结点进行平衡操作[2] 算法基本思想:通过平衡因子判断属于哪种情况,再依照情况进行平衡[3] 算法空间、时间复杂度分析:没有递归和循环,都为O(1)[4] 代码逻辑fixheight(p); //修正P的height值if (bfactor(p) == 2) 平衡因子为2,为L-?型if (bfactor(p->left) < 0) P的左孩子平衡因子<0时,为L-R型,执行left_rotate(p->left); 相关平衡操作,若>0,为L-L型。

北邮数据结构实验报告

北邮数据结构实验报告

北邮数据结构实验报告摘要:本报告基于北邮数据结构实验,通过实际操作和实验结果的分析,总结和讨论了各实验的目的、实验过程、实验结果以及相关的问题和解决方法。

本报告旨在帮助读者了解数据结构实验的基本原理和应用,并为今后的学习和研究提供参考。

1. 实验一:线性表的操作1.1 实验目的本实验旨在掌握线性表的基本操作以及对应的算法实现,包括插入、删除、查找、修改等。

1.2 实验过程我们使用C++语言编写了线性表的相关算法,并在实际编程环境下进行了测试。

通过插入元素、删除元素、查找元素和修改元素的操作,验证了算法的正确性和效率。

1.3 实验结果经过测试,我们发现线性表的插入和删除操作的时间复杂度为O(n),查找操作的时间复杂度为O(n),修改操作的时间复杂度为O(1)。

这些结果与预期相符,并反映了线性表的基本特性。

1.4 问题与解决方法在实验过程中,我们遇到了一些问题,例如插入操作的边界条件判断、删除操作时的内存释放等。

通过仔细分析问题,我们优化了算法的实现,并解决了这些问题。

2. 实验二:栈和队列的应用2.1 实验目的本实验旨在掌握栈和队列的基本原理、操作和应用,并进行实际编程实现。

2.2 实验过程我们使用C++语言编写了栈和队列的相关算法,并在实际编程环境下进行了测试。

通过栈的应用实现表达式求值和逆波兰表达式的计算,以及队列的应用实现图的广度优先遍历,验证了算法的正确性和效率。

2.3 实验结果经过测试,我们发现栈的应用可以实现表达式的求值和逆波兰表达式的计算,队列的应用可以实现图的广度优先遍历。

这些结果证明了栈和队列在实际应用中的重要性和有效性。

2.4 问题与解决方法在实验过程中,我们遇到了一些问题,例如中缀表达式转后缀表达式的算法设计、表达式求值的优化等。

通过查阅资料和与同学的讨论,我们解决了这些问题,并完善了算法的实现。

3. 实验三:串的模式匹配3.1 实验目的本实验旨在掌握串的基本操作和模式匹配算法,并进行实际编程实现。

北邮数据结构第三次实验-实验报告

北邮数据结构第三次实验-实验报告

数据结构实验报告实验名称:实验三——栈和队列学生姓名:班级:班内序号:学号:日期:1.实验要求1.1 实验目的通过选择下面两个题目之一进行实现,掌握如下内容:➢掌握二叉树基本操作的实现方法➢了解赫夫曼树的思想和相关概念➢学习使用二叉树解决实际问题的能力1.2 实验内容根据二叉树的抽象数据类型的定义,使用二叉链表实现一个二叉树。

二叉树的基本功能:1、二叉树的建立2、前序遍历二叉树3、中序遍历二叉树4、后序遍历二叉树5、按层序遍历二叉树6、求二叉树的深度7、求指定结点到根的路径8、二叉树的销毁9、其他:自定义操作编写测试main()函数测试线性表的正确性2. 程序分析2.1 二叉链表2.2 二叉树的二叉链表存储示意图2.3 关键算法分析2.3.1算法1:void create(Binode<T> *&R, T data[], int i);[1] 算法功能:创建一个二叉树[2] 算法基本思想:通过构造函数创建一个二叉树,构造函数通过调用函数create()创建二叉树,关于函数create()的伪代码:1.定义根指针,输入节点储存的data,若输入“#”,则该节点为空;2.申请一个新节点,判断它的父结点是否不为空,如果不为空在判断其为左或者右孩子,并把地址付给父结点,把data写入。

[3] 算法空间、时间复杂度:O(n)[4] 代码逻辑(可用伪代码描述):if(data[i-1]!=0){R = new Binode<T>;R->data= data[i-1];R->lch = R->rch = NULL;create(R->lch, data,2*i);create(R->rch, data, 2*i+1);}2.3.2算法2:void Destroy(Binode<T> *R);[1] 算法功能:二叉树的销毁[2] 算法基本思想:采用后序遍历的方法,释放节点。

数据结构实验报告二叉树

数据结构实验报告二叉树
return s;
}
void dispbtnode1(btnode *b)
{
btnode *st[maxsize],*p;
int level[maxsize][2],top=-1,n,i,width=4;
char type;
if(b!=NULL)
{
top++;
st[top]=b;
level[top][0]=width;
level[top][0]=n+width;
level[top][1]=1;
}
if(p->lchild!=NULL)
{
top++;
st[top]=p->lchild;
level[top][0]=n+width;
level[top][1]=0;
}
}
}
}
2)先序,中序、后序遍历功能实现,因为想自己更能读懂理解程序,没有使用递归算法。
}
btnode *rchildnode(btnode *p)
{
return p->rchild ;
}
btnode * revers(btnode *b)//交换左右子树
{
if(b!=NULL)
{
if(b->rchild !=NULL||b->lchild !=NULL)
{
btn;lchild );
(3)根据二叉树的基本运算,设计先序遍历和中序遍历(或者中序遍历和后序遍历),确定二叉树的算法。
(4)在不改变原有二叉树结构的条件下,将二叉树左右孩子进行交换,并采用凹入表示法和括号表示法输出原有二叉树及交换子树后的二叉树。

数据结构实验三——二叉树基本操作及运算实验报告

数据结构实验三——二叉树基本操作及运算实验报告

《数据结构与数据库》实验报告实验题目二叉树的基本操作及运算一、需要分析问题描述:实现二叉树(包括二叉排序树)的建立,并实现先序、中序、后序和按层次遍历,计算叶子结点数、树的深度、树的宽度,求树的非空子孙结点个数、度为2的结点数目、度为2的结点数目,以及二叉树常用运算。

问题分析:二叉树树型结构是一类重要的非线性数据结构,对它的熟练掌握是学习数据结构的基本要求。

由于二叉树的定义本身就是一种递归定义,所以二叉树的一些基本操作也可采用递归调用的方法。

处理本问题,我觉得应该:1、建立二叉树;2、通过递归方法来遍历(先序、中序和后序)二叉树;3、通过队列应用来实现对二叉树的层次遍历;4、借用递归方法对二叉树进行一些基本操作,如:求叶子数、树的深度宽度等;5、运用广义表对二叉树进行广义表形式的打印。

算法规定:输入形式:为了方便操作,规定二叉树的元素类型都为字符型,允许各种字符类型的输入,没有元素的结点以空格输入表示,并且本实验是以先序顺序输入的。

输出形式:通过先序、中序和后序遍历的方法对树的各字符型元素进行遍历打印,再以广义表形式进行打印。

对二叉树的一些运算结果以整型输出。

程序功能:实现对二叉树的先序、中序和后序遍历,层次遍历。

计算叶子结点数、树的深度、树的宽度,求树的非空子孙结点个数、度为2的结点数目、度为2的结点数目。

对二叉树的某个元素进行查找,对二叉树的某个结点进行删除。

测试数据:输入一:ABC□□DE□G□□F□□□(以□表示空格),查找5,删除E预测结果:先序遍历ABCDEGF中序遍历CBEGDFA后序遍历CGEFDBA层次遍历ABCDEFG广义表打印A(B(C,D(E(,G),F)))叶子数3 深度5 宽度2 非空子孙数6 度为2的数目2 度为1的数目2查找5,成功,查找的元素为E删除E后,以广义表形式打印A(B(C,D(,F)))输入二:ABD□□EH□□□CF□G□□□(以□表示空格),查找10,删除B预测结果:先序遍历ABDEHCFG中序遍历DBHEAGFC后序遍历DHEBGFCA层次遍历ABCDEFHG广义表打印A(B(D,E(H)),C(F(,G)))叶子数3 深度4 宽度3 非空子孙数7 度为2的数目2 度为1的数目3查找10,失败。

数据结构实验报告——树

数据结构实验报告——树

2008级数据结构实验报告实验名称:实验三树学生姓名:班级:班内序号:学号:日期:2009年11月23日1.实验要求a. 实验目的通过选择两个题目之一进行实现,掌握如下内容:掌握二叉树基本操作的实现方法了解赫夫曼树的思想和相关概念学习使用二叉树解决实际问题的能力b. 实验内容利用二叉树结构实现赫夫曼编/解码器。

基本要求:1、初始化(Init):能够对输入的任意长度的字符串s进行统计,统计每个字符的频度,并建立赫夫曼树2、建立编码表(CreateTable):利用已经建好的赫夫曼树进行编码,并将每个字符的编码输出。

3、编码(Encoding):根据编码表对输入的字符串进行编码,并将编码后的字符串输出。

4、译码(Decoding):利用已经建好的赫夫曼树对编码后的字符串进行译码,并输出译码结果。

5、打印(Print):以直观的方式打印赫夫曼树(选作)6、计算输入的字符串编码前和编码后的长度,并进行分析,讨论赫夫曼编码的压缩效果。

2. 程序分析2.1 存储结构存储结构:二叉树示意图如下:2.2 关键算法分析核心算法思想:1.哈夫曼编码(Huffman Coding)是可变字长编码。

编码时借助哈夫曼树,也即带权路径长度最小的二叉树,来建立编码。

2.哈夫曼编码可以实现无损数据压缩。

单个字符用一个特定长度的位序列替代:在字符串中出现频率高的符号,使用短的位序列,而那些很少出现的符号,则用较长的位序列。

关键算法思想描述和实现:关键算法1:统计字符出现的频度,记录出现的字符及其权值,对未出现的字符不予统计编码。

将统计的叶子节点编制成数组。

为创建哈夫曼树作准备。

C++实现:for(int i=0;str[i]!='\0';i++) //统计频度frequency[(short)str[i]]++;此处以一个一维的下标表示ascII编码,以元素之表示字符频度,解决统计字符的问题。

for(int j=0;j<128;j++) //统计叶子节点个数if(frequency[j]!=0) leaf++;此处扫描一遍上面建立的数组得到叶子节点的个数,则由(leaf*2-1)得到总的节点个数。

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

2.1 存储结构
采用二叉树的存储结构,其中每个二叉树的结点定义了一个结构体,该结构体包 含三个元素,分别是一个 T 类型的数据域 data,一个指向 T 类型的指针左孩子, 一个指向 T 类型的指针右孩子,示意图如图所示。
第1页
北京邮电大学信息与通信工程学院
第6页
北京邮电大学信息与通信工程学院
}
if (R==NULL) return d; if ((R->lch==NULL) && (R->rch==NULL)) return d+1; else { int m = GetDepth(R->lch,d+1); int n = GetDepth(R->rch,d+1); return n>m? n:m; } 1
2
3
第7页
北京邮电大学信息与通信工程学院
八:求二叉树的叶子结点数: A.自然语言描述: 1:判断根节点是否为空,如果为空,返回 0 2:如果根节点不为空,切根节点的左右孩子同时为空,返回 1 3:递归调用求二叉树的叶子节点数函数,参数改为根节点的左孩子 4:递归调用求二叉树的叶子结点数函数,参数改为根节点的右孩子 5:返回根节点的左右子树的叶子结点数之和 B.代码详细分析: template <class T> int BiTree<T>::LeafNodeCount(Node<T> *R) { if (R==NULL) return 0; if ((R->lch==NULL) && (R->rch==NULL)) return 1; else { int n=LeafNodeCount(R->lch); int m=LeafNodeCount(R->rch); return m+n; } 1 }
2
3
六:求二叉树的深度: A.自然语言描述: 1:判断根节点是否为空,如果根节点为空,返回 0 2:如果根节点不为空但是根节点的左右孩子同时为空,返回 1 3:如果以上两个条件都不成立 4:递归调用求二叉树的深度,函数的参数改为根节点的左孩子,并且深度初始化 为1 5:递归调用求二叉树的深度,函数的参数改为跟结点的右孩子,并且深度初始化 为0 6:返回 4 与 5 步中得出深度较大的那个数作为二叉树的深度数 B.代码详细分析: template <class T> int BiTree<T>::GetDepth(Node<T> *R,int d) {
第3页
北京邮电大学信息与通信工程学院
}
三:中序遍历二叉树: A.自然语言描述: 1:建立栈 2:判断该栈是否为空并且根节点是否为空指针 3:如果根节点不是空指针,将它入栈 4:入栈后将根节点指针指向它的左孩子 5:如果根节点是空指针 6:则根节点出栈,输出该节点的 data 域,并且指向根节点的指针指向它的右孩子 B. 代码详细分析: template <class T> void BiTree<T>::Inorder(Node<T> *R) { Stack<Node<T>*> S; while(!S.IsEmpty() || (R!=NULL)) { if (R!=NULL) { S.Push(R); R=R->lch; } else { R=S.Pop(); Print(R->data); R=R->rch; } }
第4页
北京邮电大学信息与通信工程学院
}
四:后序遍历二叉树: A.自然语言描述: 1:判断根节点是否为空 2:如果根节点不为空 3:递归调用后续遍历函数,函数的参数改为根节点的左孩子 4:递归调用后续遍历函数,函数的参数改为根节点的右孩子 5:输出根节点的 data 域 B.代码详细分析: template <class T> void BiTree<T>::Postorder(Node<T> *R) { if (R!=NULL) { Postorder(R->lch); Postorder(R->rch); Print(R->data); } 1 }
第8页
北京邮电大学信息与通信工程学院
int n=NodeCount(R->rch); return m+n+1; } } 1
2
3
2.3 其他
对二叉树的操作上,前序遍历与中序遍历采用了非递归算法,后续遍历,层序遍历,求 二叉树深度,求二叉树叶子结点数,求二叉树结点数等函数采用了递归算法。为了提高运算 性能,可以将它们改为非递归算法来实现,例如,后续遍历的非递归算法如下: template <class T> void BiTreee<T>::Postorder (Node<T> *R) { Stack<SNode<T>*> S; SNode<T> *p; do { while (R!=NULL) { p->ptr=R; p->tag=1;S.Push(p); R=R->lch; } while(!S.IsEmpty() && S.GetTop()->tag==2) { p=S.Pop(); cout<<p->ptr->data; } if(!S.IsEmpty()) { S.GetTop()->tag=2; R=S.GetTop()->ptr->rch; } } while(!S.IsEmpty())
2
3
九:求二叉树的结点数: A.自然语言描述: 1:判断根节点是否为空,如果为空,返回 0 2:如果根节点不为空 3:递归调用求二叉树的结点数的函数,参数改为根节点的左孩子 4:递归调用求二叉树的结点数的函数,参数改为根节点的右孩子 5:返回根节点的左右字数的结点数之和 B.代码详细分析: template <class T> int BiTree<T>::NodeCount(Node<T> *R) { if (R==NULL) return 0; else { int m=NodeCount(R->lch);
3. 程序运行结果
主函数流程图如下:
第9页
北京邮电大学信息与通信工程学院
开始
初始化一个对象
初始化字符型数组,作为赋值准备
利用 creat 函数初始化一个二叉树,参数为初始化的字符型数组
执行前序,后序,中序,层序遍历,输出遍历结果
执行求结点数,叶子节点数,二叉树深度,路径函数
执行查找数中结点元素函数
结束
第 10 页
北京邮电大学信息与通信工程学院
程序运行截图如下:
4. 总结
对二叉树的操作上,前序遍历与中序遍历采用了非递归算法,后续遍历,层序遍历,求 二叉树深度,求二叉树叶子结点数,求二叉树结点数等函数采用了递归算法。为了提高运算 性能,可以将它们改为非递归算法来实现,对于比较复杂的算法,递归和非递归的运算时间 复杂度差别较大,从性能考虑,应当优先采用非递归算法
第2页
北京邮电大学信息与通信工程学院
Create(R->lch, buf, 2*i); Create(R->rch, buf, 2*i+1); } }
A[i-1]
lch
A[2*i]
data
rch
A[2*i+1]
lch
data
rch
lch
data
rch
重复上述赋值过程,实 现递归调用 二:前序遍历二叉树: A. 自然语言描述: 1:建立栈 2:判断该栈是否为空并且根节点是否为空指针 3:如果根节点不是空指针,则输出它的 data 域,并且是它入栈 4:入栈后将根节点指针指向它的左孩子 5:如果根节点是空指针 6:则根节点出栈,并且指向根节点的指针指向它的右孩子 B.代码详细分析: template <class T> void BiTree<T>::Preorder(Node<T> *R) { Stack<Node<T>*> S; while(!S.IsEmpty() || (R!=NULL)) { if (R!=NULL) { Print(R->data); S.Push(R); R=R->lch; } else { R=S.Pop(); R=R->rch; } }
第 11 页
北京邮电大学信息与通信工程学院
源代码
使用说明:新建头文件“Function.h”和代码文件“main.cpp”, 将以下两部分代码复制到相应的头文件和代码文件后 ctrl+F5 运行即 可
Function.h:
#include<iostream> using namespace std; template <class T> class Node { public: T data; Node<T>* lch; Node<T>* rch; int ltag; int rtag; Node():lch(NULL),rch(NULL),ltag(0),rtag(0){} }; template <class T> class stacknode { public: Node<T> * treenode; int tag; }; template <class T> class BiTree {
2.2 关键算法分析
一:二叉树的建立: A. 自然语言描述: 1 首先判断调用的数组是否为空,如果为空,直接将一个已经初始化好的根节点置 为空。 2 如果该数组不为空,则把调用的数组的第一个元素的赋给根节点的 data 域。 3 采用递归的思想,分别将根节点的左右孩子作为根节点,递归调用该函数。完成 对左右子树的赋值。 B. 代码详细分析: template <class T> void BiTree<T>::Create(Node<T> *&R,T* buf,int i) { if (buf[i-1]==0) R = NULL; else { R=new Node<T>; R->data = buf[i-1];
相关文档
最新文档