算法与数据结构实验报告——树及其应用

合集下载

数据结构树的实验报告

数据结构树的实验报告

数据结构树的实验报告数据结构树的实验报告一、引言数据结构是计算机科学中的重要概念,它可以帮助我们组织和管理数据,提高程序的效率和性能。

而树作为一种常见的数据结构,具有广泛的应用。

本实验旨在通过实践操作,深入理解树的基本概念、特性和操作。

二、实验目的1. 掌握树的基本概念和特性;2. 熟悉树的基本操作,如插入、删除、查找等;3. 理解树的遍历算法,包括前序、中序和后序遍历;4. 实现树的基本功能,并验证其正确性和效率。

三、实验过程1. 构建树的数据结构首先,我们需要定义树的数据结构。

树由节点组成,每个节点可以有零个或多个子节点。

我们可以使用面向对象的思想,创建一个节点类和树类。

节点类包含节点值和子节点列表的属性,以及插入、删除子节点等操作的方法。

树类则包含根节点的属性和遍历方法等。

2. 插入和删除节点在树中插入和删除节点是常见的操作。

插入节点时,我们需要找到合适的位置,并将新节点作为子节点添加到相应的位置。

删除节点时,我们需要考虑节点的子节点和兄弟节点的关系,并进行相应的调整。

通过实现这两个操作,我们可以更好地理解树的结构和特性。

3. 查找节点树中的节点可以通过值进行查找。

我们可以使用递归或迭代的方式,在树中进行深度优先或广度优先的搜索。

在查找过程中,我们需要注意节点的存在性和唯一性,以及查找算法的效率。

4. 树的遍历树的遍历是指按照一定的顺序访问树中的所有节点。

常见的遍历方式有前序、中序和后序遍历。

前序遍历先访问根节点,然后递归地访问左子树和右子树;中序遍历先递归地访问左子树,然后访问根节点,最后访问右子树;后序遍历先递归地访问左子树和右子树,最后访问根节点。

通过实现这三种遍历算法,我们可以更好地理解树的结构和遍历过程。

五、实验结果与分析通过实验,我们成功地实现了树的基本功能,并验证了其正确性和效率。

我们可以通过插入和删除节点操作,构建出不同形态的树,并进行查找和遍历操作。

在插入和删除节点时,树的结构会发生相应的变化,但其基本特性仍然保持不变。

数据结构实验三实验报告

数据结构实验三实验报告

数据结构实验三实验报告数据结构实验三实验报告一、实验目的本次实验的目的是通过实践掌握树的基本操作和应用。

具体来说,我们需要实现一个树的数据结构,并对其进行插入、删除、查找等操作,同时还需要实现树的遍历算法,包括先序、中序和后序遍历。

二、实验原理树是一种非线性的数据结构,由结点和边组成。

树的每个结点都可以有多个子结点,但是每个结点只有一个父结点,除了根结点外。

树的基本操作包括插入、删除和查找。

在本次实验中,我们采用二叉树作为实现树的数据结构。

二叉树是一种特殊的树,每个结点最多只有两个子结点。

根据二叉树的特点,我们可以使用递归的方式实现树的插入、删除和查找操作。

三、实验过程1. 实现树的数据结构首先,我们需要定义树的结点类,包括结点值、左子结点和右子结点。

然后,我们可以定义树的类,包括根结点和相应的操作方法,如插入、删除和查找。

2. 实现插入操作插入操作是将一个新的结点添加到树中的过程。

我们可以通过递归的方式实现插入操作。

具体来说,如果要插入的值小于当前结点的值,则将其插入到左子树中;如果要插入的值大于当前结点的值,则将其插入到右子树中。

如果当前结点为空,则将新的结点作为当前结点。

3. 实现删除操作删除操作是将指定的结点从树中移除的过程。

我们同样可以通过递归的方式实现删除操作。

具体来说,如果要删除的值小于当前结点的值,则在左子树中继续查找;如果要删除的值大于当前结点的值,则在右子树中继续查找。

如果要删除的值等于当前结点的值,则有三种情况:- 当前结点没有子结点:直接将当前结点置为空。

- 当前结点只有一个子结点:将当前结点的子结点替代当前结点。

- 当前结点有两个子结点:找到当前结点右子树中的最小值,将其替代当前结点,并在右子树中删除该最小值。

4. 实现查找操作查找操作是在树中寻找指定值的过程。

同样可以通过递归的方式实现查找操作。

具体来说,如果要查找的值小于当前结点的值,则在左子树中继续查找;如果要查找的值大于当前结点的值,则在右子树中继续查找。

树及其应用的实验原理

树及其应用的实验原理

树及其应用的实验原理一、树的定义与性质树是一种常用的数据结构,它由节点和连接节点的边组成。

树的定义如下:1.每个树都有一个根节点,根节点没有父节点。

2.每个节点可以有零个或多个子节点。

3.每个非根节点都有且只有一个父节点。

4.在树中,从任意一个节点到达另一个节点的路径是唯一的。

树具有以下性质:1.树的节点可以按层次划分为不同的层级。

2.每个节点的子节点的顺序是确定的。

3.每个节点可以有任意个子节点。

二、树的表示方法树的表示方法有多种,常用的包括以下几种:1.链表实现:每个节点包含一个键和一个指向左子树和右子树的指针。

此方法的优点是方便插入和删除节点,但访问节点的时间复杂度较高。

2.数组实现:树可以被转换为一个大小为n的数组,其中n是树中节点的数量。

根节点的索引为1,左子节点的索引为2i,右子节点的索引为2i+1。

此方法的优点是访问节点的时间复杂度低,但插入和删除节点的操作较复杂。

3.哈希表实现:使用哈希表来表示树的结构,每个节点的键值对应一个哈希表的键值。

此方法的优点是查找、插入和删除操作的时间复杂度都为O(1),但空间复杂度较高。

三、树的遍历树的遍历是指按照一定的顺序访问树中的节点。

常用的树的遍历方法有三种:1.前序遍历:先访问根节点,然后按照从左到右的顺序访问左子树和右子树。

2.中序遍历:先按照从左到右的顺序访问左子树,然后访问根节点,最后访问右子树。

3.后序遍历:先按照从左到右的顺序访问左子树和右子树,然后访问根节点。

树的遍历可以使用递归或者迭代的方式来实现,其中递归是一种简单直观的方法。

四、树的应用树作为一种常见的数据结构,在计算机科学和相关领域中有广泛的应用,以下是树的一些应用场景:1.文件系统:文件系统通常使用树的结构来组织文件和目录。

每个目录是一个树节点,文件是树的叶子节点。

2.数据库索引:数据库使用树的结构来建立索引,以提高查询和插入数据的效率。

常用的索引结构包括B树和B+树。

3.编译器:编译器使用语法树来解析源代码,并生成中间代码或目标代码。

树的实现及其应用

树的实现及其应用

树的实现及其应用树(Tree)是一种非常重要的数据结构,它在计算机科学中有着广泛的应用。

树是由节点(Node)和边(Edge)组成的一种层次结构,其中一个节点可以有零个或多个子节点。

树结构中最顶层的节点称为根节点(Root),最底层的节点称为叶节点(Leaf),除了根节点外,每个节点有且仅有一个父节点。

一、树的基本概念在树的结构中,每个节点可以有多个子节点,这些子节点又可以有自己的子节点,以此类推,形成了树的层次结构。

树的基本概念包括以下几个要点:1. 根节点(Root):树结构的最顶层节点,没有父节点。

2. 叶节点(Leaf):树结构的最底层节点,没有子节点。

3. 父节点(Parent):一个节点的直接上级节点。

4. 子节点(Child):一个节点的直接下级节点。

5. 兄弟节点(Sibling):具有相同父节点的节点互为兄弟节点。

6. 子树(Subtree):树中的任意节点和它的子节点以及这些子节点的子节点构成的子树。

7. 深度(Depth):从根节点到某个节点的唯一路径的边的数量。

8. 高度(Height):从某个节点到叶节点的最长路径的边的数量。

二、树的实现树的实现可以通过多种方式来完成,其中最常见的是使用节点和指针的方式来表示树结构。

在实际编程中,可以通过定义节点类(NodeClass)来表示树的节点,然后通过指针来连接各个节点,从而构建出完整的树结构。

下面是一个简单的树节点类的示例代码:```pythonclass TreeNode:def __init__(self, value):self.value = valueself.children = []```在上面的示例中,TreeNode类表示树的节点,每个节点包含一个值(value)和一个子节点列表(children)。

通过不断地创建节点对象并将它们连接起来,就可以构建出一棵完整的树。

三、树的遍历树的遍历是指按照一定顺序访问树中的所有节点。

树的应用实验原理

树的应用实验原理

树的应用实验原理1. 引言树是一种常见的数据结构,它的应用非常广泛。

在计算机科学领域中,树的应用涉及到很多方面,包括算法、数据库、操作系统等。

本文将介绍一些树的应用实验原理。

2. 树的基本概念在开始讨论树的应用实验原理之前,我们先来回顾一下树的基本概念。

树是由节点(node)和边(edge)组成的一个非线性数据结构。

树的特点是每个节点都有零个或多个子节点,而且除了根节点,每个子节点只有一个父节点。

3. 树的应用实验原理3.1. 文件系统树被广泛应用于文件系统中,用于组织和管理文件和目录。

文件系统可以看作是一棵树,根节点表示文件系统的根目录,每个子目录表示一个节点,子目录下的文件或子目录表示子节点。

以下是文件系统树的示例: - 根目录 - 文件1 - 子目录1 - 文件2 - 子目录2 - 文件33.2. 数据库树也被广泛应用于数据库中,用于组织和存储数据。

数据库中的树通常被称为B树(B-tree),它是一种自平衡的树结构,可以高效地进行插入、删除和查找操作。

B树通常用于存储索引数据,例如在关系型数据库中,每个表可能都有一个或多个索引,用于加速数据的检索。

B树的原理是将数据按照一定的规则组织成一个树状结构,使得每个节点都包含一定范围的数据,并通过比较节点的关键字来进行快速查找。

3.3. 操作系统在操作系统中,树被用于描述进程的关系。

每个进程都有一个父进程和零个或多个子进程,这些进程之间形成了一棵进程树。

操作系统使用树的结构来实现进程的管理和调度。

根节点通常表示操作系统的初始化进程,每个子节点表示一个进程,子节点下的进程表示子进程。

通过树的结构,操作系统可以方便地管理进程之间的关系,包括创建、终止、调度等操作。

4. 总结本文介绍了树的应用实验原理。

树被广泛应用于文件系统、数据库和操作系统中。

文件系统中的树用于组织和管理文件和目录,数据库中的树用于存储索引数据,操作系统中的树用于描述进程的关系。

树的应用大大提高了数据的组织和管理效率,是计算机科学领域中非常重要的数据结构之一。

树的应用算法与数据结构

树的应用算法与数据结构

《算法与数据结构》实验报告(一) 实验题目:树的应用1、实验目的:(1)针对问题的实际要求,正确应用树形结构组织和存储数据;(2)掌握二叉树的存储方法。

(3)掌握二叉树的各种遍历方法。

2、实验内容: 二叉树后序遍历的非递归算法。

3、实验说明:二叉树后序遍历的非递归算法:结点要入两次栈,出两次栈;为了区别同一个结点的两次出栈,设置标志flag ,当结点进、出栈时,其标志flag 也同时进、出栈。

设根指针为root ,则可能有以下两种情况:⑴ 若root!=NULL ,则root 及标志flag (置为1)入栈,遍历其左子树;⑵ 若root=NULL ,此时若栈空,则整个遍历结束;若栈不空,则表明栈顶结点的左子树或右子树已遍历完毕。

若栈顶结点的标志flag=1,则表明栈顶结点的左子树已遍历完毕,将flag 修改为2,并遍历栈顶结点的右子树;若栈顶结点的标志flag=2,则表明栈顶结点的右子树也遍历完毕,输出栈顶结点。

二叉树后序遍历的非递归算法伪代码如下:设计分析在后序遍历中,在输出一个结点之前,要两次经历该结点。

第一次是从该结点出发沿其左孩子指针遍历其左子树,第二次是沿其右孩子指针遍历其右子树。

只有右子树遍历完成之后,才能访问该结点。

因此,一个结点要分两次进栈,只有第二次出栈时,才能访问该结点。

也就是说,在后序遍历中要区分是从左子树返回还是从右子树返回,在结点入栈时,必须同时压入一个标记,用该标记指明返回的情况。

所以基本思路1 第一次出栈,只遍历完左子树,该结点不能访问2 第二次出栈,遍历完右子树,该结点可以访问 flag = 1. 栈s 初始化; 2. 循环直到root 为空且栈s 为空 2.1 当root 非空时循环 2.1.1将root 连同标志flag=1入栈; 2.1.2 继续遍历root 的左子树; 2.2 当栈s 非空且栈顶元素的标志为2时,出栈并输出栈顶结点; 2.3 若栈非空,将栈顶元素的标志改为2,准备遍历栈顶结点的右子树;1.从根开始,不断将左子树指针压栈,直到指针为空为止;2.看栈顶元素如果它没有右孩子,或者它的右孩子刚被访问过,访问该结点,弹栈;转到2;否则它的右孩子不空且未被访问过,则必须将它的右孩子继续压栈;转到1;3.栈空,则结束。

数据结构实验报告

数据结构实验报告

数据结构实验报告树是一种非线性的数据结构,它由节点和边组成,节点之间存在层次关系。

树的应用十分广泛,特别是在存储和检索数据上。

在本次实验中,我对树的应用进行了研究和实践,并撰写了本篇实验报告。

本次实验中,我首先学习了树的基本概念和相关术语。

树由根节点、子节点、叶节点以及它们之间的连接边组成。

每个节点可以有多个子节点,但只能有一个父节点(除了根节点)。

叶节点是没有子节点的节点。

这种层次结构使得树可以用来表示具有层次关系的数据,例如家谱、目录结构等。

接下来,我学习了树的不同种类和它们的特点。

最常见的树结构包括二叉树、二叉树(BST)、平衡二叉树、AVL树等。

二叉树是一种每个节点最多有两个子节点的树结构。

二叉树是二叉树的一种特殊形式,其中左子树的所有节点值都小于根节点的值,右子树的所有节点值都大于根节点的值。

平衡二叉树是一种高度平衡的二叉树,它的左右子树的高度差不超过1、AVL树是一种自平衡的二叉树,它通过旋转和重新平衡来保持树的平衡性。

为了更好地理解树的应用,我选择了二叉树(BST)作为本次实验的主要研究对象。

BST是一种高效的数据结构,可以用来存储一组有序的数据,并且支持快速的查找、插入和删除操作。

我首先实现了BST的基本操作,包括插入节点、删除节点和查找节点。

通过这些操作,我可以在BST中存储和检索数据。

在插入节点时,我按照BST的特性将节点插入到相应的位置,并保持树的有序性。

在删除节点时,我考虑了不同的情况,包括删除叶节点、删除只有一个子节点的节点以及删除有两个子节点的节点。

在查找节点时,我使用了递归的方式在树中查找节点的值。

接着,我实现了一些BST的扩展操作。

首先是中序遍历,它可以按照节点的值的升序输出BST中的所有节点。

其次是最小值和最大值的查找,它们分别返回BST中的最小值和最大值。

最后是查找一些节点的前驱和后继,前驱是小于该节点的最大节点,后继是大于该节点的最小节点。

这些扩展操作可以进一步提升BST的功能和灵活性。

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

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

实验5:树(二叉树)(采用二叉链表存储)一、实验项目名称二叉树及其应用二、实验目的熟悉二叉树的存储结构的特性以及二叉树的基本操作。

三、实验基本原理之前我们都是学习的线性结构,这次我们就开始学习非线性结构——树。

线性结构中结点间具有唯一前驱、唯一后继关系,而非线性结构中结点的前驱、后继的关系并不具有唯一性。

在树结构中,节点间关系是前驱唯一而后继不唯一,即结点之间是一对多的关系。

直观地看,树结构是具有分支关系的结构(其分叉、分层的特征类似于自然界中的树)。

四、主要仪器设备及耗材Window 11、Dev-C++5.11五、实验步骤1.导入库和预定义2.创建二叉树3.前序遍历4.中序遍历5.后序遍历6.总结点数7.叶子节点数8.树的深度9.树根到叶子的最长路径10.交换所有节点的左右子女11.顺序存储12.显示顺序存储13.测试函数和主函数对二叉树的每一个操作写测试函数,然后在主函数用while+switch-case的方式实现一个带菜单的简易测试程序,代码见“实验完整代码”。

实验完整代码:#include <bits/stdc++.h>using namespace std;#define MAX_TREE_SIZE 100typedef char ElemType;ElemType SqBiTree[MAX_TREE_SIZE];struct BiTNode{ElemType data;BiTNode *l,*r;}*T;void createBiTree(BiTNode *&T){ElemType e;e = getchar();if(e == '\n')return;else if(e == ' ')T = NULL;else{if(!(T = (BiTNode *)malloc(sizeof (BiTNode)))){cout << "内存分配错误!" << endl;exit(0);}T->data = e;createBiTree(T->l);createBiTree(T->r);}}void createBiTree2(BiTNode *T,int u) {if(T){SqBiTree[u] = T->data;createBiTree2(T->l,2 * u + 1);createBiTree2(T->r,2 * u + 2); }}void outputBiTree2(int n){int cnt = 0;for(int i = 0;cnt <= n;i++){cout << SqBiTree[i];if(SqBiTree[i] != ' ')cnt ++;}cout << endl;}void preOrderTraverse(BiTNode *T) {if(T){cout << T->data;preOrderTraverse(T->l);preOrderTraverse(T->r);}}void inOrderTraverse(BiTNode *T) {if(T){inOrderTraverse(T->l);cout << T->data;inOrderTraverse(T->r);}}void beOrderTraverse(BiTNode *T){if(T){beOrderTraverse(T->l);beOrderTraverse(T->r);cout << T->data;}}int sumOfVer(BiTNode *T){if(!T)return 0;return sumOfVer(T->l) + sumOfVer(T->r) + 1;}int sumOfLeaf(BiTNode *T){if(!T)return 0;if(T->l == NULL && T->r == NULL)return 1;return sumOfLeaf(T->l) + sumOfLeaf(T->r);}int depth(BiTNode *T){if(!T)return 0;return max(depth(T->l),depth(T->r)) + 1;}bool LongestPath(int dist,int dist2,vector<ElemType> &ne,BiTNode *T) {if(!T)return false;if(dist2 == dist)return true;if(LongestPath(dist,dist2 + 1,ne,T->l)){ne.push_back(T->l->data);return true;}else if(LongestPath(dist,dist2 + 1,ne,T->r)){ne.push_back(T->r->data);return true;}return false;}void swapVer(BiTNode *&T){if(T){swapVer(T->l);swapVer(T->r);BiTNode *tmp = T->l;T->l = T->r;T->r = tmp;}}//以下是测试程序void test1(){getchar();cout << "请以先序次序输入二叉树结点的值,空结点用空格表示:" << endl; createBiTree(T);cout << "二叉树创建成功!" << endl;}void test2(){cout << "二叉树的前序遍历为:" << endl;preOrderTraverse(T);cout << endl;}void test3(){cout << "二叉树的中序遍历为:" << endl;inOrderTraverse(T);cout << endl;}void test4(){cout << "二叉树的后序遍历为:" << endl;beOrderTraverse(T);cout << endl;}void test5(){cout << "二叉树的总结点数为:" << sumOfVer(T) << endl;}void test6(){cout << "二叉树的叶子结点数为:" << sumOfLeaf(T) << endl; }void test7(){cout << "二叉树的深度为:" << depth(T) << endl;}void test8(){int dist = depth(T);vector<ElemType> ne;cout << "树根到叶子的最长路径:" << endl;LongestPath(dist,1,ne,T);ne.push_back(T->data);reverse(ne.begin(),ne.end());cout << ne[0];for(int i = 1;i < ne.size();i++)cout << "->" << ne[i];cout << endl;}void test9(){swapVer(T);cout << "操作成功!" << endl;}void test10(){memset(SqBiTree,' ',sizeof SqBiTree);createBiTree2(T,0);cout << "操作成功!" << endl;}void test11(){int n = sumOfVer(T);outputBiTree2(n);}int main(){int op = 0;while(op != 12){cout << "-----------------menu--------------------" << endl;cout << "--------------1:创建二叉树--------------" << endl;cout << "--------------2:前序遍历----------------" << endl;cout << "--------------3:中序遍历----------------" << endl;cout << "--------------4:后序遍历----------------" << endl;cout << "--------------5:总结点数----------------" << endl;cout << "--------------6:叶子节点数--------------" << endl;cout << "--------------7:树的深度----------------" << endl;cout << "--------------8:树根到叶子的最长路径----" << endl;cout << "--------------9:交换所有节点左右子女----" << endl;cout << "--------------10:顺序存储---------------" << endl;cout << "--------------11:显示顺序存储-----------" << endl;cout << "--------------12:退出测试程序-----------" << endl;cout << "请输入指令编号:" << endl;if(!(cin >> op)){cin.clear();cin.ignore(INT_MAX,'\n');cout << "请输入整数!" << endl;continue;}switch(op){case 1:test1();break;case 2:test2();break;case 3:test3();break;case 4:test4();break;case 5:test5();break;case 6:test6();break;case 7:test7();break;case 8:test8();break;case 9:test9();break;case 10:test10();break;case 11:test11();break;case 12:cout << "测试结束!" << endl;break;default:cout << "请输入正确的指令编号!" << endl;}}return 0;}六、实验数据及处理结果测试用例:1.创建二叉树(二叉链表形式)2.前序遍历3.中序遍历4.后序遍历5.总结点数6.叶子结点数7.树的深度8.树根到叶子的最长路径9.交换所有左右子女10.顺序存储七、思考讨论题或体会或对改进实验的建议通过这次实验,我掌握了二叉树的顺序存储和链式存储,体会了二叉树的存储结构的特性,掌握了二叉树的树上相关操作。

树及应用实验报告

树及应用实验报告

树及应用实验报告实验目的研究树结构及其应用,了解树的基本概念和常见操作,掌握树在实际问题中的运用。

实验内容1. 树结构的定义和特点2. 常见树的实现方式3. 二叉树及其操作4. 树的遍历算法5. 树在排序和搜索中的应用6. 树在图算法中的应用实验步骤与结果1. 树结构的定义和特点树是一种非线性的数据结构,由节点和边组成。

一个节点可以有多个子节点,但每个节点只有一个父节点。

树具有以下特点:- 树中只有一个根节点,它没有父节点。

- 每个非根节点有且只有一个父节点。

- 除了根节点外,每个节点可以有零个或多个子节点。

- 节点之间通过边连接。

2. 常见树的实现方式树可以通过链表或数组两种方式进行实现。

链表实现的树称为链式树,数组实现的树称为顺序树。

链式树的节点是通过指针进行连接的,每个节点包含数据和指向子节点的指针。

链式树的优点是插入和删除节点方便,缺点是访问节点需要遍历链表。

顺序树将节点存储在一个数组中,通过计算索引值来访问对应位置的节点。

顺序树的优点是访问节点快速,缺点是插入和删除节点困难。

3. 二叉树及其操作二叉树是一种特殊的树结构,每个节点最多有两个子节点。

二叉树的操作包括插入节点、删除节点、查找节点等。

二叉树的插入节点操作如下:1. 如果树为空,则将新节点作为根节点。

2. 如果新节点的值小于当前节点的值,则将新节点插入到当前节点的左子树中。

3. 如果新节点的值大于当前节点的值,则将新节点插入到当前节点的右子树中。

二叉树的删除节点操作如下:1. 如果要删除的节点是叶子节点,则直接删除它。

2. 如果要删除的节点只有一个子节点,则将子节点替代要删除的节点。

3. 如果要删除的节点有两个子节点,则将它的后继节点替代要删除的节点。

4. 树的遍历算法树的遍历算法包括先序遍历、中序遍历和后序遍历。

先序遍历按照根节点、左子树、右子树的顺序遍历树。

中序遍历按照左子树、根节点、右子树的顺序遍历树。

后序遍历按照左子树、右子树、根节点的顺序遍历树。

算法与数据结构实验报告——树及其应用

算法与数据结构实验报告——树及其应用

北京邮电大学软件学院2019-2020学年第1学期实验报告课程名称:算法与数据结构课程设计实验名称:树及其应用实验完成人:日期: 2019 年 11月 10 日一、实验目的树是一种应用极为广泛的数据结构,也是这门课程的重点。

它们的特点在于非线性。

广义表本质上是树结构。

本章实验继续突出了数据结构加操作的程序设计观点,但根据这两种结构的非线性特点,将操作进一步集中在遍历操作上,因为遍历操作是其他众多操作的基础。

遍历逻辑的(或符号形式的)结构,访问动作可是任何操作。

本次实验希望帮助学生熟悉各种存储结构的特征,以及如何应用树结构解决具体问题(即原理与应用的结合)。

二、实验内容必做内容1)二叉树的建立与遍历[问题描述]建立一棵二叉树,并对其进行遍历(先序、中序、后序),打印输出遍历结果。

[基本要求]从键盘接受输入(先序),以二叉链表作为存储结构,建立二叉树(以先序来建立),并采用递归算法对其进行遍历(先序、中序、后序),将遍历结果打印输出。

[测试数据]ABCффDEфGффFффф(其中ф表示空格字符)则输出结果为先序:ABCDEGF中序:CBEGDFA后序:CGBFDBA2)打印二叉树结构[问题描述]按凹入表形式横向打印二叉树结构,即二叉树的根在屏幕的最左边,二叉树的左子树在屏幕的下边,二叉树的右子树在屏幕的上边。

例如:[测试数据]由学生依据软件工程的测试技术自己确定。

注意测试边界数据,如空二叉树。

[实现提示](1)利用RDL遍历方法;(2)利用结点的深度控制横向位置。

选做内容采用非递归算法实现二叉树遍历。

三、实验环境Windows下利用vs 2019完成,语言c++四、实验过程描述首先构造Tree类,内含树的结构体BiTree,以及本实验所要用到的一些操作typedef struct BiTNode{TElemType data;int degree, depth, level; //度,高度,高度差struct BiTNode* lchild, * rchild; /* 左右孩子指针 */}BiTNode, * BiTree;实现相应功能:1、二叉树的建立与遍历构造二叉树:前序构造,先赋值,然后递归构造左子树,递归构造右函数BiTNode* Tree::CreatBiTree(BiTree T) {TElemType ch;cin >> noskipws >> ch; //不跳过空格if (ch == ' ')T = NULL; //输入空格表示空子树else {T = new BiTNode; //分配空间if(!T) //分配失败就退出throw new std::bad_alloc;T->degree = 0; //记录度(T)->data = ch;T->depth++; //度增加T->lchild=CreatBiTree(T->lchild); //递归创建左子树T->rchild=CreatBiTree(T->rchild); //递归创建右子树if (T->lchild != NULL)T->degree++; //有一个孩子度就加一if (T->rchild != NULL)T->degree++;}return T;}销毁二叉树:后序递归销毁左右子树(需要先查找到子树,销毁再销毁父亲树)void Tree::Release(BiTree T) {if (T != NULL) {Release(T->lchild); //递归销毁左子树Release(T->rchild); //递归销毁右子树delete T;}}//前序遍历void Tree::PreOrderTraverse(BiTree T, void(Tree::*Visit)(BiTree)) { if (T) /* T不空 */{(this->*Visit)(T); /* 先访问根结点 */PreOrderTraverse(T->lchild, Visit); /* 再先序遍历左子树 */PreOrderTraverse(T->rchild, Visit); /* 最后先序遍历右子树 */ }}//中序遍历void Tree::InOrderTraverse(BiTree T, void(Tree::*Visit)(BiTree)) {if (T){InOrderTraverse(T->lchild, Visit); /* 先中序遍历左子树 */(this->*Visit)(T); /* 再访问根结点 */InOrderTraverse(T->rchild, Visit); /* 最后中序遍历右子树 */ }}//后序遍历void Tree::PostOrderTraverse(BiTree T, void(Tree::*Visit)(BiTree)) {if (T){PostOrderTraverse(T->lchild, Visit); /* 先中序遍历左子树 */PostOrderTraverse(T->rchild, Visit); /* 最后中序遍历右子树 */(this->*Visit)(T); /* 再访问根结点 */}}//查找深度int Tree::TreeDepth(BiTree T) {int i, j;if (!T)return 0; /* 空树深度为0 */if (T->lchild)i = TreeDepth(T->lchild); /* i为左子树的深度 */elsei = 0;if (T->rchild)j = TreeDepth(T->rchild); /* j为右子树的深度 */elsej = 0;T->depth = i > j ? i + 1 : j + 1;return T->depth;}//得到层数void Tree::getLevel(BiTree T, int level){if (T){T->level = level;getLevel(T->lchild, level + 1); //得到左子树的层数,左子树根节点的层数比此节点多一getLevel(T->rchild, level + 1); //得到右子树的层数,右子树根节点的层数比此节点多一}}//非递归中序遍历void Tree::NoRecInOrderTraverse(BiTree T, void(Tree::*Visit)(BiTree)) {LinkedStack<BiTree> S;BiTree p = T;while (p || !S.isEmpty()) {if (p) {S.Push(p); //当节点不为空时就压栈,然后判断左孩子p = p->lchild;}else {p=S.Pop(); //返回到父节点(this->*Visit)(p); //访问p = p->rchild; //然后指向右节点}}}实验二:2、打印二叉树结构//中序遍历RDLvoid Tree::InOrderTraverseRDL(BiTree T, void(Tree::* Visit)(BiTree)) {if (T){InOrderTraverseRDL(T->rchild, Visit); /* 先中序遍历左子树 */(this->*Visit)(T); /* 再访问根结点 */InOrderTraverseRDL(T->lchild, Visit); /* 最后中序遍历右子树 */ }}//打印二叉树图形打印图形时,需要中序遍历RDL(先遍历右节点,再遍历右节点)。

实验五树结构及其应用

实验五树结构及其应用

实验五树结构及其应用本实验根据树结构的非线性特点,将操作集中在遍历操作上,因为遍历操作是其他众多操作的基础。

本实验还希望达到使学生熟悉各种存储结构的特征,以及掌握如何应用树解决具体问题(即原理与应用的结合)等目的。

1.二叉树的建立与遍历(验证性实验)【问题描述】建立一棵二叉树,并对其进行遍历(先序、中序和后序),打印输出遍历结果。

【基本要求】从键盘接受输入(先序序列),以二叉链表作为存储结构,建立二叉树(以先序来建立),并采用递归算法对其进行遍历(先序、中序和后序),将遍历结果打印输出。

【测试数据】ABC##DE#G##F###(其中#表示空),则输出结果为:先序为ABCDEGF,中序为CBEGDF A,后序为CGBFDBA。

2. 利用二叉树的遍历算法的基本操作(设计性实验)【问题描述】利用二叉树的遍历算法:●求二叉树的结点数;●求二叉树的叶结点数;●求二叉树的高度。

【基本要求】(1) 按第1题中的方法建立二叉链表存储的二叉树。

(2) 提供菜单选择计算结点数、叶结点数、高度。

【提示】●求二叉树的结点数;⏹1+左子树的结点数+右子树的结点数●求二叉树的叶结点数;⏹左子树的叶结点数+右子树的叶结点数●求二叉树的高度。

⏹1+(左、右子树高度较大的值)【测试数据】A如图中的二叉树,结点数:6个叶结点数:2个高度:43.赫夫曼编码(综合性实验)(选做)【问题描述】设某编码系统共有n个字符,使用频率分别为w1, w2, …, w n,设计一个不等长的编码方案,使得该编码系统的空间效率最好。

【基本要求】(1)初始化(Initialization)。

从终端读入一段英文字符,统计每个字符出现的频率,建立赫夫曼树;(2)编码(Encoding)。

利用建好的赫夫曼树对各字符进行编码,用列表的形式显示在屏幕上,并将编码结果输出;(3)译码(Decoding)。

利用已建好的赫夫曼树对编码进行译码,结果输出。

以下内容虽难度提高,但比较有意思,推荐有能力的同学选做,或者2-3个同学讨论后共同开发,具体功能及完成程度不做限制。

树的操作及应用实验报告

树的操作及应用实验报告

树的操作及应用实验报告实验名称:树的操作及应用实验报告摘要:本实验旨在通过实际操作掌握树的基本操作,并对树的应用进行实现和分析。

实验主要包括创建树、遍历树、搜索树和删除树等操作,并应用树的特点解决实际问题。

一、引言树是一种非线性的数据结构,由若干个节点组成,节点之间通过边连接。

树的基本概念包括根节点、子节点、父节点、叶节点等。

树具有分支结构,适用于描述具有层次关系的实际问题。

二、目的1. 理解树的基本概念和操作。

2. 掌握树的遍历操作。

3. 了解搜索树的特点和应用。

4. 熟悉树的删除操作。

三、实验设备和材料1. 计算机。

2. 编程语言:C++。

四、实验步骤与结果1. 创建树:通过定义节点结构和树结构,使用代码创建树,并初始化树的根节点。

2. 遍历树:实现树的前序遍历、中序遍历和后序遍历。

通过调用递归函数,遍历树的所有节点,并将节点值输出。

3. 搜索树:实现二叉搜索树,并应用搜索树的特性进行搜索操作。

首先,通过插入节点操作创建一棵二叉搜索树。

然后,通过比较搜索值与节点值的大小,逐步定位搜索值所在的位置。

最后,输出搜索结果。

4. 删除树:实现树的删除操作。

通过递归调用函数,将树的每个节点依次删除,并释放内存。

五、实验结果分析1. 创建树的操作能够成功地创建一棵树,并初始化根节点。

2. 遍历树的操作能够按照前序、中序和后序的顺序遍历所有节点,并正确输出节点值。

3. 搜索树的操作能够根据搜索值的大小,快速地定位并输出搜索结果。

4. 删除树的操作能够依次删除树的每个节点,并及时释放内存。

六、实验结论通过本实验,我们掌握了树的基本操作,并应用树的特点解决了实际问题。

树作为一种非线性数据结构,具有广泛的应用价值,在算法和数据处理中发挥着重要作用。

七、实验感想通过本次实验,我们深入理解了树的结构和操作,并学会了如何应用树来解决实际问题。

树的递归结构使得其遍历和搜索操作非常高效,能够快速地定位和处理数据。

同时,树的删除操作也需要特别小心,避免出现内存泄漏等问题。

数据结构中的树与的应用

数据结构中的树与的应用

数据结构中的树与的应用数据结构中的树与其应用树是一种常见的数据结构,它由节点和边组成,用于表示具有层次关系的数据。

在计算机科学领域,树结构被广泛应用于各种领域,包括数据库系统、图形算法、操作系统等等。

本文将介绍树的基本概念以及在数据结构中的应用。

一、树的基本概念树由节点和边组成,其中一个节点被指定为根节点,其他节点根据其关系被分为若干个子树。

每个节点可以有任意数量的子节点,而每个子节点又可以有自己的子节点。

树的节点可以包含数据元素,这些数据元素可以是任意类型的。

树的基本特性包括根节点、子节点、叶节点和父节点。

根节点是整棵树的起点,没有父节点;子节点是一个节点的直接后继节点,它们共享一个直接的父节点;叶节点是没有子节点的节点,它们是树的末端节点;父节点是一个节点的直接前驱节点,它是与一个或多个子节点相连的节点。

树的高度是指树中任意节点到叶节点的最长路径的长度。

树的深度是指根节点到该节点的路径长度。

典型的树包括二叉树、二叉搜索树、平衡二叉树和B树等。

二、树的应用1. 文件系统树被广泛应用于文件系统的表示和管理中。

文件系统通常被组织成树的形式,其中根节点表示整个文件系统,每个子节点代表一个文件夹或文件。

这种树结构的好处是可以方便地进行文件的查找和管理,同时支持文件夹的嵌套和层次结构。

2. 数据库系统在数据库系统中,树被用于实现索引结构以提高查询效率。

例如,二叉搜索树是一种常用的数据结构,它可以用于快速查找和插入数据。

在数据库中,索引树常用于加速基于关键字的查询操作,它可以将查询的时间复杂度从O(n)降低到O(log n)。

3. 图形算法树结构也在图形算法中得到了广泛应用。

例如,最小生成树算法可以用于在一个加权连通图中找到一棵包含所有顶点的树,且边的权重之和最小。

最短路径算法也可以使用树结构辅助查找两个顶点之间的最短路径。

4. 操作系统操作系统中的进程调度算法和内存管理也经常使用树结构。

例如,调度算法中可以使用优先级树来决定哪个进程优先被执行。

数据结构实验三:树的应用

数据结构实验三:树的应用

数据结构实验报告实验三树的应用一、实验目的:1.掌握二叉树基本操作;2.掌握构造哈夫曼树及哈夫曼编码的方法二、实验要求:1.C完成算法设计和程序设计并上机调试通过。

2.撰写实验报告,提供实验结果和数据。

3.写出算法设计小结和心得。

三、实验内容:1.采用二叉链表存储结构,编写程序实现按层次遍历二叉树。

2.从键盘输入若干字符,统计每个字符出现的频率,将字符出现的频率作为结点的权值,建立哈夫曼树,然后对各个字符进行哈夫曼编码,最后打印输出每个字符及对应的哈夫曼编码。

一个完整的哈夫曼编码/译码系统应具有以下功能:(1)初始化:从终端读入一段英文字符,统计每个字符出现的频率,建立哈夫曼树;(2)编码:利用建好的哈夫曼树对各字符进行编码,并输出结果(要求输出哈夫曼树存储结构的初态、终态及字符的哈夫曼编码);(3)译码:利用已建立的哈夫曼编码对输入的字符序列进行译码,并输出结果;(选做)(4)解码:利用哈夫曼编码,对任意输入的0、1序列能正确解码,并输出结果。

(选做)四、程序源代码:(1)#include "stdio.h"#include "conio.h"#include "stdlib.h"typedef char TElemType;typedef struct BiTNode{TElemType data;struct BiTNode *lchild,*rchild;}BiTNode,*BiTree;/*创建二叉树*/void create(BiTree *T){char c;scanf("%c",&c);if(c!='#'){*T=(BiTree)malloc(sizeof(BiTNode)); (*T)->data=c; create(&((*T)->rchild));}else *T=NULL;}/*按层遍历*/void Traverse(BiTree T){BiTree Queue[20]; BiTree p;int front=0,rear=0;if(T){p=T;Queue[rear]=p;rear=(rear+1)%20;while(front!=rear){p=Queue[front];printf("%c",p->data);front=(front+1)%20;{Queue[rear]=p->lchild;rear=(rear+1)%20;}if(p->rchild){Queue[rear]=p->rchild;rear=(rear+1)%20;}}}}main(){BiTree T;create(&T);Traverse(T);getch();}(2)#include<stdio.h>#include<conio.h>#include<iostream.h>#include<string.h>#include<stdlib.h>#define MAXVALUE 10000#define MAXLEAF 30#define MAXNODE MAXLEAF*2-1#define MAXBIT 50typedef struct node /*结点类型定义*/ {char letter;int weight;int parent;int lchild;int rchild;}HNodeType;typedef struct /*编码类型定义*/ {char letter;int bit[MAXBIT];int start;}HCodeType; typedef struct /*输入符号的类型*/{char s;int num;}lable;void HuffmanTree(HNodeType HuffNode[],int n,lable a[]){int i,j,m1,m2,x1,x2,temp1;char temp2;for (i=0;i<2*n-1;i++) /*结点初始化*/{HuffNode[i].letter=0;HuffNode[i].weight=0;HuffNode[i].parent=-1;HuffNode[i].lchild=-1;HuffNode[i].rchild=-1;}for (i=0;i<n-1;i++)for (j=i+1;j<n-1;j++)if (a[j].num>a[i].num){temp1=a[i].num;a[i].num=a[j].num;a[j].num=temp1;temp2=a[i].s;a[i].s=a[j].s;a[j].s=temp2;}for (i=0;i<n;i++){HuffNode[i].weight=a[i].num;HuffNode[i].letter=a[i].s;}for (i=0;i<n-1;i++) /*构造huffman 树*/{m1=m2=MAXVALUE;x1=x2=0;for (j=0;j<n+i;j++){(HuffNode[j].parent==-1&&HuffNode[j].weight <m1){m2=m1;x2=x1;m1=HuffNode[j].weight;x1=j;}else if (HuffNode[j].parent==-1&&HuffNode[j].weight <m2){m2=HuffNode[j].weight;x2=j;}}HuffNode[x1].parent=n+i;HuffNode[x2].parent=n+i;HuffNode[n+i].weight=HuffNode[x1].weight+Hu ffNode[x2].weight;HuffNode[n+i].lchild=x1;HuffNode[n+i].rchild=x2;}}void HuffmanCode(int n,lable a[]){HNodeType HuffNode[MAXNODE];HCodeType HuffCode[MAXLEAF],cd;int i,j,c,p;HuffmanTree(HuffNode,n,a);for (i=0;i<n;i++) /*按结点位置进行编码*/{cd.start=n-1;c=i;p=HuffNode[c].parent;while (p!=-1){if (HuffNode[p].lchild==c)cd.bit[cd.start]=0;else cd.bit[cd.start]=1; c=p;p=HuffNode[c].parent;}for (j=cd.start+1;j<n;j++) /*储存编码*/HuffCode[i].bit[j]=cd.bit[j];HuffCode[i].start=cd.start;}for (i=0;i<n;i++){HuffCode[i].letter=HuffNode[i].letter;printf(" %c ",HuffCode[i].letter);for (j=HuffCode[i].start+1;j<n;j++)printf("%d",HuffCode[i].bit[j]);printf("\n");}}int main(){lable data[30];char s[100],*p;int i,count=0;for (;;){cout<<" / 求哈夫曼编码,输入end结束 /"<<endl;printf(" 输入字符:");scanf("%s",s);if (!strcmp(s,"end"))exit(0);for (i=0;i<30;i++){data[i].s=0;data[i].num=0;}p=s;while (*p) /*计算字符个数与出现次数*/{for (i=0;i<=count+1;i++)if (data[i].s==0){data[i].s=*p;data[i].num++;count++;break;}else if (data[i].s==*p){data[i].num++;break;}}p++;}printf("\n");printf(" 不同字符数:%d\n",count);for (i=0;i<count;i++){printf(" %c ",data[i].s);printf("weight:%d\n",data[i].num);}HuffmanCode(count,data);count=0;}getch();}五、测试结果(1)(2)六、小结(包括收获、心得体会、存在的问题及解决问题的方法、建议等)本次实验第一个学习了二叉树的一些基本操作,通过编码实现对二叉树按层次遍历,以使我们对二叉树有更加深入的理解。

数据结构实验报告

数据结构实验报告

数据结构实验报告本次数据结构实验的主要内容是关于树的相关操作,包括树的创建、遍历、查找等。

通过实验,我们将对树的基本概念和操作进行深入了解,并掌握相关算法的实现和应用。

首先,我们将介绍树的创建和基本操作。

树是一种非线性数据结构,由节点和边组成,具有层次关系。

在实验中,我们通过数组和链表两种方式来创建树。

数组表示法是将树的节点按照从上到下、从左到右的顺序存储在一维数组中,通过计算节点的下标来实现对树的操作。

链表表示法则是利用指针来表示节点之间的关系,实现树的各种操作。

在创建树的过程中,我们需要考虑节点的插入、删除和修改等操作,以及树的遍历方式,包括前序遍历、中序遍历和后序遍历。

其次,我们将介绍树的查找操作。

在实际应用中,我们经常需要对树进行查找操作,以找到特定的节点或者进行相关的数据处理。

在本次实验中,我们将学习如何实现对树的查找操作,包括深度优先搜索(DFS)和广度优先搜索(BFS)两种方式。

通过这些查找算法,我们可以高效地找到树中的特定节点,并进行相应的处理。

最后,我们将进行树的应用实例分析。

树作为一种重要的数据结构,在实际应用中有着广泛的应用。

我们将通过实例分析,介绍树在各种领域的应用,包括文件系统、数据库索引、网络路由等方面。

通过这些实例,我们可以更好地理解树的重要性和实际应用。

总之,本次数据结构实验涉及了树的创建、遍历、查找和应用等方面,通过实验,我们将对树的相关概念和操作有更深入的理解,并掌握相关算法的实现和应用。

希望通过本次实验,能够对数据结构有更深入的认识,为今后的学习和应用打下良好的基础。

数据结构-树的实现实验报告

数据结构-树的实现实验报告

数据结构-树的实现实验报告数据结构-树的实现实验报告1-引言在计算机科学中,树是一种非常重要的数据结构,它可以用来模拟现实世界中的层次关系。

本实验旨在通过实现树的基本操作,加深对树数据结构的理解和掌握。

2-实验目的本实验的主要目标是:●理解树这种数据结构的基本概念和特点。

●学习树的常见操作,包括插入节点、删除节点、查找节点等。

●掌握树的遍历算法,包括前序遍历、中序遍历、后序遍历和层次遍历。

●实现树的基本操作,并验证其正确性。

3-实验设计3-1 树的定义首先,我们需要明确树的定义。

树是一种由节点和边组成的数据结构,具有以下特点:●每个节点都有零个或多个子节点。

●除了根节点外,每个节点都有且仅有一个父节点。

●没有父节点的节点称为根节点。

●没有子节点的节点称为叶子节点。

●在任意一棵树中,从根节点到任意一个节点都存在唯一一条路径。

3-2 树的实现我们可以通过链式存储结构来实现树。

每个节点包含一个数据域和一个指向子节点的指针域。

根据树的特点,我们可以定义一个树的节点类,如下所示:```javaclass TreeNode {Object data。

// 节点数据TreeNode parent。

// 父节点指针List<TreeNode> children。

// 子节点指针public TreeNode(Object data) {this(data, null, new ArrayList<>())。

}public TreeNode(Object data, TreeNode parent,List<TreeNode> children) {this-data = data。

this-parent = parent。

this-children = children。

}}```在树的实现中,我们还需要定义一些基本操作,包括插入节点、删除节点、查找节点等。

3-2-1 插入节点插入节点是将一个新节点插入到树中的指定位置。

树形结构及应用 实验报告

树形结构及应用 实验报告

实验报告课程名称:数据结构与算法课程类型:必修实验项目名称:实验题目:树形结构及应用一、实验目的树型结构的建立与遍历树型结构的遍历是树型结构算法的基础,本实验要求编写程序演示二叉树的存储结构的建立和遍历过程。

二、实验要求及实验环境实验要求:(1)编写建立二叉树的二叉链表存储结构的程序,并横版和竖版两种方式显示该二叉树;(2) 在(1)所建二叉树的基础上,编写程序完成先序、中序和后序遍历的递归和非递归实现并显示相应的遍历序列;(3) 在二叉树的二叉链表存储结构基础上,编写程序实现二叉树的先序或中序或后序线索链表存储结构建立的算法,并(用广义表的形式)显示和保存二叉树的相应的线索链表;中序线索链表广义表显示示例:1(2(4(0,2), 1), 3(6(1,3),7(3,0)))(4) 在二叉树的线索链表存储结构上,编写程序分别实现求一个结点的先序(中序、后序)的后继结点的算法;(先序、中序、后序可以任选一种实现)(5) 在 (4) 基础上,编写程序实现对线索二叉树进行先序(中序、后序)遍历的非递归算法,并显示线索二叉树和相应的遍历序列。

实验环境:运行C或c++的微机。

三、设计思想(本程序中的用到的所有数据类型的定义,主程序的流程图及各程序模块之间的调用关系)1.逻辑设计2.物理设计1.二叉树数据类型:typedef struct BiTNode{char data;struct BiTNode *lchild,*rchild;}BiTNode,*BiTree;2.线索二叉树数据类型:typedef struct BiThreTree{DataType data; //定义结点元素PointerTag LTag,RTag;struct BiThreTree *lchild,*rchild;}BiThreTree;3.中序,前序,后序遍历函数大致相同以中序为例,递归void inorder(BiTree T){ //中序遍历二叉树并输出if(T != NULL){inorder(T->lchild);printf("%c",T->data);inorder(T->rchild);}}三、测试结果1.线索二叉树建立,中序遍历,搜索结点,输出后继结点2.二叉树的建立,输入,显示,遍历,广义表五、系统不足与经验体会1. 经验体会:熟悉了二叉树这种数据结构,并了解其应用,例如求前驱后继结点。

1605120107_胡志豪_实验报告06-树的应用

1605120107_胡志豪_实验报告06-树的应用

《算法与数据结构》实验报告
2
计算机科学与工程学院
实验内容: 二叉树遍历及其应用的递归算法。 实验说明: (共 24 个算法) 定义二叉树的链式存储结构,实现下列各类应用的递归算法。 (1)构建一棵二叉树,以某种形式(括号表示法、树形表示法、凹入表示 法等)输出二叉树,最后释放二叉树的存储内存。 (2)分别编写程序实现:将二叉树的顺序存储结构转换成链式存储结构; 将二叉树的链式存储结构转换为顺序存储结构。 (3)实现二叉树的先序、中序、后序和层次序遍历算法。输出二叉树的叶 子节点。 (4)分别计算二叉树的所有节点个数,度为 0、1、2 的节点个数。 (5)统计二叉树中值为 k 的节点个数。计算二叉树中节点最小的值。 (6)计算二叉树的高度。计算二叉树中节点的层数。 (7)实现两棵二叉树的复制。交换二叉树的左右子树。判断两棵二叉树是 否相似。 (8)输出二叉树中根节点到每个叶子节点的路径。 (9)分别编写程序实现:给定二叉树的中序遍历序列和先序遍历序列,构 造该二叉树;给定二叉树的中序遍历序列和后序遍历序列,构造该二叉树。
《算法与数据结构》实验报告 3
计算机科学与工程学院
ch=str[j]; while(ch!='\0') { switch(ch) { case'(':top++;St[top]=;k=1;break; case')':top--;break; case',':k=2;break; default:p=(BTNode*)malloc(sizeof(BTNode)); p->data=ch; p->lchild=p->rchild=NULL; if(b=NULL) b=p; else { switch(k) { case1:St[top]->lchild=p;break; case2:St[top]->rchild=p;break; } } } j++; ch=str[j]; } } void DispBTree(BTNode* b) { if(b!=NULL) { printf("%c",b->data); if(b->lchild!=NULL||b->rchild!=NULL) { printf("("); DispBTree(b->lchild); if(b->rchild!=NULL)printf(","); DispBTree(b->rchild); printf(")"); } } } void DestroyBTree(BTNode *& b) { if(b!=NULL)

数据结构树的实验报告

数据结构树的实验报告

数据结构树的实验报告数据结构树的实验报告引言:数据结构是计算机科学中的重要基础,它涉及到如何组织和存储数据以便有效地使用。

树是一种常见的数据结构,它具有层次结构和分支特征,被广泛应用于各个领域。

本实验旨在通过实践操作和观察,深入理解树的特性和应用。

一、实验目的本实验的目的是通过实践操作,掌握树的基本概念、特性和常见操作。

具体目标包括:1. 了解树的基本概念和术语;2. 掌握树的构建和遍历方法;3. 理解树的应用场景和相关算法。

二、实验过程1. 树的构建在本实验中,我们使用Python编程语言实现了树的构建。

首先,我们定义了树的节点类,节点包含一个值和指向子节点的指针。

然后,我们通过递归的方式构建了一棵树,树的每个节点都可以有多个子节点。

2. 树的遍历树的遍历是指按照一定的顺序访问树的所有节点。

在本实验中,我们实现了树的三种遍历方式:前序遍历、中序遍历和后序遍历。

前序遍历是先访问根节点,然后依次递归遍历左子树和右子树;中序遍历是先递归遍历左子树,然后访问根节点,最后递归遍历右子树;后序遍历是先递归遍历左子树和右子树,最后访问根节点。

3. 树的应用树作为一种重要的数据结构,在实际应用中有着广泛的应用。

在本实验中,我们选择了两个常见的树的应用场景进行了实践操作。

(1)文件系统文件系统可以看作是一棵树,根目录为根节点,各级子目录和文件为子节点。

通过实践操作,我们可以模拟文件系统的创建、删除、查找等操作,加深对树的理解。

(2)家谱家谱也可以看作是一棵树,根节点为家族的祖先,各级子节点为后代。

通过实践操作,我们可以实现家谱的构建、查询和修改,了解家谱的组织和维护方式。

三、实验结果与分析通过实验操作,我们成功构建了树的数据结构,并实现了树的遍历和应用。

在文件系统的实践中,我们能够灵活地创建、删除和查找文件和目录,实现了对文件系统的基本操作。

在家谱的实践中,我们能够方便地构建和查询家族成员的关系,加深了对家谱的理解。

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

北京邮电大学软件学院2019-2020学年第1学期实验报告课程名称:算法与数据结构课程设计实验名称:树及其应用实验完成人:日期: 2019 年 11月 10 日一、实验目的树是一种应用极为广泛的数据结构,也是这门课程的重点。

它们的特点在于非线性。

广义表本质上是树结构。

本章实验继续突出了数据结构加操作的程序设计观点,但根据这两种结构的非线性特点,将操作进一步集中在遍历操作上,因为遍历操作是其他众多操作的基础。

遍历逻辑的(或符号形式的)结构,访问动作可是任何操作。

本次实验希望帮助学生熟悉各种存储结构的特征,以及如何应用树结构解决具体问题(即原理与应用的结合)。

二、实验内容必做内容1)二叉树的建立与遍历[问题描述]建立一棵二叉树,并对其进行遍历(先序、中序、后序),打印输出遍历结果。

[基本要求]从键盘接受输入(先序),以二叉链表作为存储结构,建立二叉树(以先序来建立),并采用递归算法对其进行遍历(先序、中序、后序),将遍历结果打印输出。

[测试数据]ABCффDEфGффFффф(其中ф表示空格字符)则输出结果为先序:ABCDEGF中序:CBEGDFA后序:CGBFDBA2)打印二叉树结构[问题描述]按凹入表形式横向打印二叉树结构,即二叉树的根在屏幕的最左边,二叉树的左子树在屏幕的下边,二叉树的右子树在屏幕的上边。

例如:[测试数据]由学生依据软件工程的测试技术自己确定。

注意测试边界数据,如空二叉树。

[实现提示](1)利用RDL遍历方法;(2)利用结点的深度控制横向位置。

选做内容采用非递归算法实现二叉树遍历。

三、实验环境Windows下利用vs 2019完成,语言c++四、实验过程描述首先构造Tree类,内含树的结构体BiTree,以及本实验所要用到的一些操作typedef struct BiTNode{TElemType data;int degree, depth, level; //度,高度,高度差struct BiTNode* lchild, * rchild; /* 左右孩子指针 */}BiTNode, * BiTree;实现相应功能:1、二叉树的建立与遍历构造二叉树:前序构造,先赋值,然后递归构造左子树,递归构造右函数BiTNode* Tree::CreatBiTree(BiTree T) {TElemType ch;cin >> noskipws >> ch; //不跳过空格if (ch == ' ')T = NULL; //输入空格表示空子树else {T = new BiTNode; //分配空间if(!T) //分配失败就退出throw new std::bad_alloc;T->degree = 0; //记录度(T)->data = ch;T->depth++; //度增加T->lchild=CreatBiTree(T->lchild); //递归创建左子树T->rchild=CreatBiTree(T->rchild); //递归创建右子树if (T->lchild != NULL)T->degree++; //有一个孩子度就加一if (T->rchild != NULL)T->degree++;}return T;}销毁二叉树:后序递归销毁左右子树(需要先查找到子树,销毁再销毁父亲树)void Tree::Release(BiTree T) {if (T != NULL) {Release(T->lchild); //递归销毁左子树Release(T->rchild); //递归销毁右子树delete T;}}//前序遍历void Tree::PreOrderTraverse(BiTree T, void(Tree::*Visit)(BiTree)) { if (T) /* T不空 */{(this->*Visit)(T); /* 先访问根结点 */PreOrderTraverse(T->lchild, Visit); /* 再先序遍历左子树 */PreOrderTraverse(T->rchild, Visit); /* 最后先序遍历右子树 */ }}//中序遍历void Tree::InOrderTraverse(BiTree T, void(Tree::*Visit)(BiTree)) {if (T){InOrderTraverse(T->lchild, Visit); /* 先中序遍历左子树 */(this->*Visit)(T); /* 再访问根结点 */InOrderTraverse(T->rchild, Visit); /* 最后中序遍历右子树 */ }}//后序遍历void Tree::PostOrderTraverse(BiTree T, void(Tree::*Visit)(BiTree)) {if (T){PostOrderTraverse(T->lchild, Visit); /* 先中序遍历左子树 */PostOrderTraverse(T->rchild, Visit); /* 最后中序遍历右子树 */(this->*Visit)(T); /* 再访问根结点 */}}//查找深度int Tree::TreeDepth(BiTree T) {int i, j;if (!T)return 0; /* 空树深度为0 */if (T->lchild)i = TreeDepth(T->lchild); /* i为左子树的深度 */elsei = 0;if (T->rchild)j = TreeDepth(T->rchild); /* j为右子树的深度 */elsej = 0;T->depth = i > j ? i + 1 : j + 1;return T->depth;}//得到层数void Tree::getLevel(BiTree T, int level){if (T){T->level = level;getLevel(T->lchild, level + 1); //得到左子树的层数,左子树根节点的层数比此节点多一getLevel(T->rchild, level + 1); //得到右子树的层数,右子树根节点的层数比此节点多一}}//非递归中序遍历void Tree::NoRecInOrderTraverse(BiTree T, void(Tree::*Visit)(BiTree)) {LinkedStack<BiTree> S;BiTree p = T;while (p || !S.isEmpty()) {if (p) {S.Push(p); //当节点不为空时就压栈,然后判断左孩子p = p->lchild;}else {p=S.Pop(); //返回到父节点(this->*Visit)(p); //访问p = p->rchild; //然后指向右节点}}}实验二:2、打印二叉树结构//中序遍历RDLvoid Tree::InOrderTraverseRDL(BiTree T, void(Tree::* Visit)(BiTree)) {if (T){InOrderTraverseRDL(T->rchild, Visit); /* 先中序遍历左子树 */(this->*Visit)(T); /* 再访问根结点 */InOrderTraverseRDL(T->lchild, Visit); /* 最后中序遍历右子树 */ }}//打印二叉树图形打印图形时,需要中序遍历RDL(先遍历右节点,再遍历右节点)。

每一个字符占一行,所在的列根据此节点的层数来确定。

(void printT(BiTree T) { //打印二叉树图形for (int i = 0; i < T->level; i++) {cout <<" ";}cout <<T->data << endl;}实验3:采用非递归算法实现二叉树遍历利用栈来模拟操作系统调用函数判断该节点是否为空,如果不为空就压栈,否则弹出栈中最上层元素//非递归前序遍历void Tree::NoRecPreOrderTraverse(BiTree T, void(Tree::* Visit)(BiTree)) {LinkedStack<BiTree> S;BiTree p = T;while (p || !S.isEmpty()) {if (p) {(this->*Visit)(p); //先访问S.Push(p);p = p->lchild; //当节点不为空时就压栈,然后判断左孩子}else { //节点为空时p = S.Pop(); //返回到父节点然后指向右节点p = p->rchild;}}}//非递归后序遍历后序遍历时如果当前结点左右子树均为空,则可以访问当前结点,或者左右子树不均为空,但是前一个访问的结点是当前结点的左孩子或者右孩子,则也可以访问当前结点否则则压入栈中。

压栈时先压右节点再压左节点。

void Tree::NoRecPostOrderTraverse(BiTree T, void(Tree::*Visit)(BiTree)) {LinkedStack<BiTree> S;S.Push(T); //将根节点压栈BiTree pre = NULL; //前一个节点BiTree cur; //现在的节点while (!S.isEmpty()) //如果栈不为空就一直进行{cur = S.Peek(); //观测现在的节点,不弹出if (( cur->lchild==NULL && cur->rchild==NULL ) //左右子树不均为空|| ( pre!=NULL &&( pre== cur->rchild||pre==cur->lchild))) //或前一个访问的结点是当前结点的左孩子或者右孩子,则可以访问{(this->*Visit)(cur);cur = S.Pop(); //弹出此节点pre = cur; //改变现在的pre}else{if (cur->rchild != NULL ){S.Push(cur->rchild); //如果右孩子不为空就压入栈}if ( cur->lchild !=NULL ){S.Push(cur->lchild); //如果左孩子不为空就压入栈}}}}void visitT(BiTree T) { //输出节点上的字符数据cout <<T->data;}五、实验结果:输入两组树,分别进行相关运算,得到如下结果:六、源代码:LinkedStack.h栈的模板类#pragma once#include<exception>template< typename T>struct Node {T data;Node<T>* next;};template< typename T>class LinkedStack{private:Node<T>* top;public:LinkedStack();~LinkedStack();void Push(T);T Pop();T Peek();bool isEmpty();};template< typename T> LinkedStack<T>::LinkedStack() { top = nullptr;}template< typename T> LinkedStack<T>::~LinkedStack() { Node<T>* p = nullptr;while (top){p = top;top = top->next;delete p;}}template< typename T>void LinkedStack<T>::Push(T e) { Node<T>* p = new Node<T>;p->data = e;p->next = top;top = p;}template< typename T>T LinkedStack<T>::Pop() {if (!top)throw - 1; //如果为空则失败Node<T>* p = top;T e = p->data;top = top->next;delete p;p = NULL;return e;}template< typename T>T LinkedStack<T>::Peek() {if (!top)throw - 1; //如果为空则失败T e = top->data;return e;}template< typename T>bool LinkedStack<T>::isEmpty() {return top == nullptr;}Tree.h#pragma once#include<iostream>#include<string>#include"LinkedStack.h"using namespace std;typedef char TElemType;typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */ typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */typedef struct BiTNode{TElemType data;int degree, depth, level; //度,高度,高度差struct BiTNode* lchild, * rchild; /* 左右孩子指针 */}BiTNode, * BiTree;class Tree{private:BiTree root;int rootDepth;BiTNode* CreatBiTree(BiTree T); //构造二叉树void Release(BiTree T); //销毁二叉树void InOrderTraverse(BiTree, void(Tree::*Visit)(BiTree)); //中序遍历void InOrderTraverseRDL(BiTree, void(Tree::* Visit)(BiTree)); //RDL 中序遍历void PostOrderTraverse(BiTree, void(Tree::*Visit)(BiTree));//后序遍历void PreOrderTraverse(BiTree, void(Tree::*Visit)(BiTree));//前序遍历int TreeDepth(BiTree T); //测量树的深度void getLevel(BiTree, int); //测量树的层数(节点所在层数)void NoRecPreOrderTraverse(BiTree, void(Tree::*Visit)(BiTree)); //非递归前序遍历void NoRecInOrderTraverse(BiTree, void(Tree::*Visit)(BiTree));//非递归中序遍历void NoRecPostOrderTraverse(BiTree, void(Tree::*Visit)(BiTree));//非递归后序遍历public:Tree() { //构造函数,调用CreatBiTree()root = NULL;root = CreatBiTree(root);rootDepth = TreeDepth(root);getLevel(root, 1);}~Tree(){ //析构函数Release(root);}void visitT(BiTree T) { //输出节点上的字符数据cout <<T->data;}void printT(BiTree T) { //打印二叉树图形for (int i = 0; i < T->level; i++) {cout <<" ";}cout <<T->data << endl;}//下面的几个函数是为了给外部调用而设计的void PreOrderTraverse(void(Tree::*Visit)(BiTree)) {PreOrderTraverse(root, Visit);}void InOrderTraverse(void(Tree::*Visit)(BiTree)) {InOrderTraverse(root, Visit);}void InOrderTraverseRDL(void(Tree::* Visit)(BiTree)) { InOrderTraverseRDL(root, Visit);}void PostOrderTraverse(void(Tree::*Visit)(BiTree)) { PostOrderTraverse(root, Visit);}void NoRecPreOrderTraverse(void(Tree::*Visit)(BiTree)) { NoRecPreOrderTraverse(root, Visit);}void NoRecInOrderTraverse(void(Tree::*Visit)(BiTree)) { NoRecInOrderTraverse(root, Visit);}void NoRecPostOrderTraverse(void(Tree::*Visit)(BiTree)) { NoRecPostOrderTraverse(root, Visit);}};Tree.cpp#include"Tree.h"//构造二叉树BiTNode* Tree::CreatBiTree(BiTree T) {TElemType ch;cin >> noskipws >> ch; //不跳过空格if (ch == ' ')T = NULL; //输入空格表示空子树else {T = new BiTNode; //分配空间if(!T) //分配失败就退出throw new std::bad_alloc;T->degree = 0; //记录度(T)->data = ch;T->depth++; //度增加T->lchild=CreatBiTree(T->lchild); //递归创建左子树T->rchild=CreatBiTree(T->rchild); //递归创建右子树if (T->lchild != NULL)T->degree++; //有一个孩子度就加一if (T->rchild != NULL)T->degree++;}return T;}//销毁二叉树void Tree::Release(BiTree T) {if (T != NULL) {Release(T->lchild); //递归销毁左子树Release(T->rchild); //递归销毁右子树delete T;}}//前序遍历void Tree::PreOrderTraverse(BiTree T, void(Tree::*Visit)(BiTree)) { if (T) /* T不空 */{(this->*Visit)(T); /* 先访问根结点 */PreOrderTraverse(T->lchild, Visit); /* 再先序遍历左子树 */PreOrderTraverse(T->rchild, Visit); /* 最后先序遍历右子树 */ }}//中序遍历void Tree::InOrderTraverse(BiTree T, void(Tree::*Visit)(BiTree)) {if (T){InOrderTraverse(T->lchild, Visit); /* 先中序遍历左子树 */(this->*Visit)(T); /* 再访问根结点 */InOrderTraverse(T->rchild, Visit); /* 最后中序遍历右子树 */ }}//中序遍历RDLvoid Tree::InOrderTraverseRDL(BiTree T, void(Tree::* Visit)(BiTree)) {if (T){InOrderTraverseRDL(T->rchild, Visit); /* 先中序遍历左子树 */(this->*Visit)(T); /* 再访问根结点 */InOrderTraverseRDL(T->lchild, Visit); /* 最后中序遍历右子树 */ }}//后序遍历void Tree::PostOrderTraverse(BiTree T, void(Tree::*Visit)(BiTree)) {if (T){PostOrderTraverse(T->lchild, Visit); /* 先中序遍历左子树 */PostOrderTraverse(T->rchild, Visit); /* 最后中序遍历右子树 */(this->*Visit)(T); /* 再访问根结点 */}}//查找深度int Tree::TreeDepth(BiTree T) {int i, j;if (!T)return 0; /* 空树深度为0 */if (T->lchild)i = TreeDepth(T->lchild); /* i为左子树的深度 */elsei = 0;if (T->rchild)j = TreeDepth(T->rchild); /* j为右子树的深度 */elsej = 0;T->depth = i > j ? i + 1 : j + 1;return T->depth;}//得到层数void Tree::getLevel(BiTree T, int level){if (T){T->level = level;getLevel(T->lchild, level + 1); //得到左子树的层数,左子树根节点的层数比此节点多一getLevel(T->rchild, level + 1); //得到右子树的层数,右子树根节点的层数比此节点多一}}//非递归前序遍历void Tree::NoRecPreOrderTraverse(BiTree T, void(Tree::* Visit)(BiTree)) {LinkedStack<BiTree> S;BiTree p = T;while (p || !S.isEmpty()) {if (p) {(this->*Visit)(p); //先访问S.Push(p);p = p->lchild; //当节点不为空时就压栈,然后判断左孩子}else {p = S.Pop(); //返回到父节点然后指向右节点p = p->rchild;}}}//非递归中序遍历void Tree::NoRecInOrderTraverse(BiTree T, void(Tree::*Visit)(BiTree)) {LinkedStack<BiTree> S;BiTree p = T;while (p || !S.isEmpty()) {if (p) {S.Push(p); //当节点不为空时就压栈,然后判断左孩子p = p->lchild;}else {p=S.Pop(); //返回到父节点(this->*Visit)(p); //访问p = p->rchild; //然后指向右节点}}}//非递归后序遍历void Tree::NoRecPostOrderTraverse(BiTree T, void(Tree::*Visit)(BiTree)) {LinkedStack<BiTree> S;S.Push(T); //将根节点压栈BiTree pre = NULL; //前一个节点BiTree cur; //现在的节点while (!S.isEmpty()) //如果栈不为空就一直进行{cur = S.Peek(); //观测现在的节点,不弹出if (( cur->lchild==NULL && cur->rchild==NULL ) //左右子树不均为空|| ( pre!=NULL &&( pre== cur->rchild||pre==cur->lchild))) //或前一个访问的结点是当前结点的左孩子或者右孩子,则可以访问{(this->*Visit)(cur);cur = S.Pop(); //弹出此节点pre = cur; //改变现在的pre}else{if (cur->rchild != NULL ){S.Push(cur->rchild); //如果右孩子不为空就压入栈}if ( cur->lchild !=NULL ){S.Push(cur->lchild); //如果左孩子不为空就压入栈}}}}Main.cpp#include"Tree.h"int main() {cout <<"输入一个树:"<< endl;Tree *a = new Tree();cout <<"前序遍历:"<< endl;a->PreOrderTraverse(&Tree::visitT);cout << endl;cout <<"中序遍历:"<< endl;a->InOrderTraverse(&Tree::visitT);cout << endl;cout <<"后序遍历:"<< endl;a->PostOrderTraverse(&Tree::visitT);cout << endl;cout <<"打印图形:"<< endl;a->InOrderTraverseRDL(&Tree::printT);cout << endl;cout <<"非递归前序遍历:"<< endl;a->NoRecPreOrderTraverse(&Tree::visitT);cout << endl;cout <<"非递归中序遍历:"<< endl;a->NoRecInOrderTraverse(&Tree::visitT);cout << endl;cout <<"非递归后序遍历:"<< endl;a->NoRecPostOrderTraverse(&Tree::visitT);}。

相关文档
最新文档