数据结构树的实现实验报告
数据结构树的实验报告
数据结构树的实验报告数据结构树的实验报告一、引言数据结构是计算机科学中的重要概念,它可以帮助我们组织和管理数据,提高程序的效率和性能。
而树作为一种常见的数据结构,具有广泛的应用。
本实验旨在通过实践操作,深入理解树的基本概念、特性和操作。
二、实验目的1. 掌握树的基本概念和特性;2. 熟悉树的基本操作,如插入、删除、查找等;3. 理解树的遍历算法,包括前序、中序和后序遍历;4. 实现树的基本功能,并验证其正确性和效率。
三、实验过程1. 构建树的数据结构首先,我们需要定义树的数据结构。
树由节点组成,每个节点可以有零个或多个子节点。
我们可以使用面向对象的思想,创建一个节点类和树类。
节点类包含节点值和子节点列表的属性,以及插入、删除子节点等操作的方法。
树类则包含根节点的属性和遍历方法等。
2. 插入和删除节点在树中插入和删除节点是常见的操作。
插入节点时,我们需要找到合适的位置,并将新节点作为子节点添加到相应的位置。
删除节点时,我们需要考虑节点的子节点和兄弟节点的关系,并进行相应的调整。
通过实现这两个操作,我们可以更好地理解树的结构和特性。
3. 查找节点树中的节点可以通过值进行查找。
我们可以使用递归或迭代的方式,在树中进行深度优先或广度优先的搜索。
在查找过程中,我们需要注意节点的存在性和唯一性,以及查找算法的效率。
4. 树的遍历树的遍历是指按照一定的顺序访问树中的所有节点。
常见的遍历方式有前序、中序和后序遍历。
前序遍历先访问根节点,然后递归地访问左子树和右子树;中序遍历先递归地访问左子树,然后访问根节点,最后访问右子树;后序遍历先递归地访问左子树和右子树,最后访问根节点。
通过实现这三种遍历算法,我们可以更好地理解树的结构和遍历过程。
五、实验结果与分析通过实验,我们成功地实现了树的基本功能,并验证了其正确性和效率。
我们可以通过插入和删除节点操作,构建出不同形态的树,并进行查找和遍历操作。
在插入和删除节点时,树的结构会发生相应的变化,但其基本特性仍然保持不变。
数据结构树的操作实验报告
*******************实践教学*******************兰州理工大学算法与数据结构课程设计题目:二叉树操作专业班级:08级计算机科学与技术(5)班姓名:金文鑫学号:08240511指导教师:李睿成绩:_______________一、实验目的:理解二叉树特别是完全二叉树的性质,掌握二叉树的存储结构(二叉链表);熟练掌握二叉树的常用操作算法(初始化、插入结点、删除结点、遍历等);初步掌握二叉树的应用。
二、实验内容:要求采用二叉链表作为存储结构,完成二叉树的建立,前序、中序和后序遍历的操作,求所有叶子及结点总数的操作等。
具体要求如下:①给出基于二叉链表的二叉树类的定义;②给出二叉树初始化(构造函数)的实现;③给出二叉树三种遍历算法的递归实现;④二叉树先序遍历的非递归算法实现;⑤利用二叉树的遍历算法求二叉树的结点数、二叉树的叶结点数、二叉树的高度;⑥二叉树的撤销删除三、实验步骤:1、需求分析:本演示程序用JA V A编写,完成树的生成,任意位置的插入、删除,以及遍历二叉树中的结点,查找和修改树中元素的值。
①输入的形式和输入值的范围:插入元素时需要输入插入的位置和元素的值;删除元素时输入删除元素的位置;遍历时采用三种遍历方法中的一种遍历方法;修改操作时需要输入的元素的值;查找操作时,需要找到要查找元素的位置。
在所有输入中,元素的值都是整数。
②输出的形式:在所有四种操作中都显示操作是否正确以及操作后树中的内容。
其中删除操作后显示删除的元素的值,遍历二叉树中的元素,查找操作、修改操作后显示修改的值。
③程序所能达到的功能:完成树的生成(通过插入操作)、插入、删除、遍历、查找、修改操作。
④测试数据:A.树中已有以50,25,75,12,37,43,30,33,87,93,97为关键字的结点B.插入操作中依次输入10,20,30,40,50,60,70,80,90,100十个数C.删除操作中输入10删除值为10的元素D.查找操作中输入20,30,40,50返回这个元素在树中的位置2.概要设计:1)为了实现上述程序功能,需要定义树的抽象数据类型:public int iData;public double dData;public Node leftChild;public Node rightChild;private Node root;int value;private Node getSuccessor;基本操作:{Tree ()操作结果:构造一个空的二叉树insert ()初始条件:是否存在一个空二叉树操作结果:往二叉树中插入数值delete ()初始条件:存在一非空的二叉树操作条件:将二叉树中的元素删除displayTree ()初始条件:存在一非空的树操作条件:显示非空树中的所有元素的值getString ()初始条件:存在一非空的二叉树操作结果:返回整个字符串的数值getChar ()初始条件:存在一非空的二叉树操作结果:返回字符型的数值getInt ()初始条件:存在一非空的二叉树操作结果:返回整型的数值find ()初始条件:存在一非空二叉树操作结果:从二叉树中查找某一元素traverse ()初始条件:存在一非空的二叉树操作结果:对二叉树中的元素进行遍历preorder ()初始条件:存在一非空的二叉树操作结果:对二叉树中的元素进行先根遍历inOrder ()初始条件:存在一非空的二叉树操作结果:对二叉树中的元素进行中根遍历postOrder ()初始条件:存在一非空的二叉树操作结果:对二叉树中的元素进行后根遍历DisplayNode ()初始条件:存在一非空的二叉树操作结果:显示出二叉树中的整形数值和双精度浮点型数值public static void main操作结果:调用主函数2)本程序包含14个函数:3.详细设计实现概要设计中定义的所有的数据类型,对每个操作给出java算法。
数据结构实验三实验报告
数据结构实验三实验报告数据结构实验三实验报告一、实验目的本次实验的目的是通过实践掌握树的基本操作和应用。
具体来说,我们需要实现一个树的数据结构,并对其进行插入、删除、查找等操作,同时还需要实现树的遍历算法,包括先序、中序和后序遍历。
二、实验原理树是一种非线性的数据结构,由结点和边组成。
树的每个结点都可以有多个子结点,但是每个结点只有一个父结点,除了根结点外。
树的基本操作包括插入、删除和查找。
在本次实验中,我们采用二叉树作为实现树的数据结构。
二叉树是一种特殊的树,每个结点最多只有两个子结点。
根据二叉树的特点,我们可以使用递归的方式实现树的插入、删除和查找操作。
三、实验过程1. 实现树的数据结构首先,我们需要定义树的结点类,包括结点值、左子结点和右子结点。
然后,我们可以定义树的类,包括根结点和相应的操作方法,如插入、删除和查找。
2. 实现插入操作插入操作是将一个新的结点添加到树中的过程。
我们可以通过递归的方式实现插入操作。
具体来说,如果要插入的值小于当前结点的值,则将其插入到左子树中;如果要插入的值大于当前结点的值,则将其插入到右子树中。
如果当前结点为空,则将新的结点作为当前结点。
3. 实现删除操作删除操作是将指定的结点从树中移除的过程。
我们同样可以通过递归的方式实现删除操作。
具体来说,如果要删除的值小于当前结点的值,则在左子树中继续查找;如果要删除的值大于当前结点的值,则在右子树中继续查找。
如果要删除的值等于当前结点的值,则有三种情况:- 当前结点没有子结点:直接将当前结点置为空。
- 当前结点只有一个子结点:将当前结点的子结点替代当前结点。
- 当前结点有两个子结点:找到当前结点右子树中的最小值,将其替代当前结点,并在右子树中删除该最小值。
4. 实现查找操作查找操作是在树中寻找指定值的过程。
同样可以通过递归的方式实现查找操作。
具体来说,如果要查找的值小于当前结点的值,则在左子树中继续查找;如果要查找的值大于当前结点的值,则在右子树中继续查找。
数据结构-树的实现实验报告
对某个具体的抽象数据类型,运用课程所学的知识和方法,设计合理的数据结构,并在此基础上实现该抽象数据类型的全部基本操作。通过本设计性实验,检验所学知识和能力,发现学习中存在的问题。进而达到熟练地运用本课程中的基础知识及技术的目的。
3.实验环境
1、硬件:PC机
2、软件:Microsoft Visual C++ 6.0
typedef struct LinkQueue
{
QueuePtr front,rear; /*队头、队尾指针*/
}LinkQueue;
/*******************************队列定义**************************************/
/*构造一个空队列*/
const char NIL=' ';
/*****************树的二叉链表孩子-兄弟-双亲存储表示***************************/
typedef struct CSnode
{
char data;
CSnode *firstchild,*nextsibling,*parent;
int InitQueue (LinkQueue &Q)
{
if(!(Q.front=Q.rear=new QNode))
exit(OVERFLOW);
Q.front->next=NULL;
return OK;
}
/*销毁队列Q*/
int DestroyQueue(LinkQueue &Q)
{
while(Q.front){
void Print(CSTree T,void (*visit)(CSTree));
数据结构实验报告
数据结构实验报告树是一种非线性的数据结构,它由节点和边组成,节点之间存在层次关系。
树的应用十分广泛,特别是在存储和检索数据上。
在本次实验中,我对树的应用进行了研究和实践,并撰写了本篇实验报告。
本次实验中,我首先学习了树的基本概念和相关术语。
树由根节点、子节点、叶节点以及它们之间的连接边组成。
每个节点可以有多个子节点,但只能有一个父节点(除了根节点)。
叶节点是没有子节点的节点。
这种层次结构使得树可以用来表示具有层次关系的数据,例如家谱、目录结构等。
接下来,我学习了树的不同种类和它们的特点。
最常见的树结构包括二叉树、二叉树(BST)、平衡二叉树、AVL树等。
二叉树是一种每个节点最多有两个子节点的树结构。
二叉树是二叉树的一种特殊形式,其中左子树的所有节点值都小于根节点的值,右子树的所有节点值都大于根节点的值。
平衡二叉树是一种高度平衡的二叉树,它的左右子树的高度差不超过1、AVL树是一种自平衡的二叉树,它通过旋转和重新平衡来保持树的平衡性。
为了更好地理解树的应用,我选择了二叉树(BST)作为本次实验的主要研究对象。
BST是一种高效的数据结构,可以用来存储一组有序的数据,并且支持快速的查找、插入和删除操作。
我首先实现了BST的基本操作,包括插入节点、删除节点和查找节点。
通过这些操作,我可以在BST中存储和检索数据。
在插入节点时,我按照BST的特性将节点插入到相应的位置,并保持树的有序性。
在删除节点时,我考虑了不同的情况,包括删除叶节点、删除只有一个子节点的节点以及删除有两个子节点的节点。
在查找节点时,我使用了递归的方式在树中查找节点的值。
接着,我实现了一些BST的扩展操作。
首先是中序遍历,它可以按照节点的值的升序输出BST中的所有节点。
其次是最小值和最大值的查找,它们分别返回BST中的最小值和最大值。
最后是查找一些节点的前驱和后继,前驱是小于该节点的最大节点,后继是大于该节点的最小节点。
这些扩展操作可以进一步提升BST的功能和灵活性。
数据结构实验报告——树
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. 理解树的基本概念和操作。
2. 掌握树的创建、插入、删除、查找等基本操作。
3. 熟悉树在计算机科学中的应用。
实验环境:1. 操作系统:Windows 102. 编程语言:Java3. 开发工具:Eclipse实验内容:1. 树的基本概念2. 树的创建3. 树的插入4. 树的删除5. 树的查找6. 树的应用实验步骤:一、树的基本概念1. 树的定义:树是一种非线性数据结构,由若干节点组成,每个节点有一个唯一的父节点(根节点除外),除了根节点外,其他节点都有一个子节点。
2. 树的术语:- 节点:树中的数据元素。
- 父节点:节点的直接前驱节点。
- 子节点:节点的直接后继节点。
- 根节点:没有父节点的节点。
- 叶节点:没有子节点的节点。
- 节点的度:节点拥有的子节点个数。
- 树的深度:根节点到叶节点的最长路径长度。
二、树的创建1. 创建二叉树:```javapublic class BinaryTree {private TreeNode root;public BinaryTree() {root = null;}public void createTree(int[] data) {if (data == null || data.length == 0) {return;}root = new TreeNode(data[0]);int i = 1;Queue<TreeNode> queue = new LinkedList<>(); queue.offer(root);while (!queue.isEmpty()) {TreeNode node = queue.poll();if (i < data.length && data[i] != 0) {node.left = new TreeNode(data[i]); queue.offer(node.left);i++;}if (i < data.length && data[i] != 0) { node.right = new TreeNode(data[i]); queue.offer(node.right);i++;}}}}```2. 创建二叉搜索树:```javapublic class BinarySearchTree {private TreeNode root;public BinarySearchTree() {root = null;}public void createTree(int[] data) {if (data == null || data.length == 0) {return;}for (int i = 0; i < data.length; i++) {root = insert(root, data[i]);}}private TreeNode insert(TreeNode node, int data) { if (node == null) {return new TreeNode(data);}if (data < node.data) {node.left = insert(node.left, data);} else if (data > node.data) {node.right = insert(node.right, data);}return node;}}```三、树的插入1. 在二叉树中插入节点:```javapublic void insert(TreeNode node, int data) {if (node == null) {return;}if (data < node.data) {insert(node.left, data);} else if (data > node.data) {insert(node.right, data);}}```2. 在二叉搜索树中插入节点:```javaprivate TreeNode insert(TreeNode node, int data) { if (node == null) {return new TreeNode(data);}if (data < node.data) {node.left = insert(node.left, data);} else if (data > node.data) {node.right = insert(node.right, data);}return node;}```四、树的删除1. 在二叉树中删除节点:```javapublic void delete(TreeNode node, int data) {if (node == null) {return;}if (data < node.data) {delete(node.left, data);} else if (data > node.data) {delete(node.right, data);} else {if (node.left == null && node.right == null) { node = null;} else if (node.left == null) {node = node.right;} else if (node.right == null) {node = node.left;} else {TreeNode minNode = findMin(node.right);node.data = minNode.data;delete(node.right, minNode.data);}}}```2. 在二叉搜索树中删除节点:```javaprivate TreeNode delete(TreeNode node, int data) {if (node == null) {return null;}if (data < node.data) {node.left = delete(node.left, data);} else if (data > node.data) {node.right = delete(node.right, data);} else {if (node.left == null && node.right == null) { node = null;} else if (node.left == null) {node = node.right;} else if (node.right == null) {node = node.left;} else {TreeNode minNode = findMin(node.right);node.data = minNode.data;node.right = delete(node.right, minNode.data); }}return node;}```五、树的查找1. 在二叉树中查找节点:```javapublic TreeNode search(TreeNode node, int data) {if (node == null) {return null;}if (data == node.data) {return node;} else if (data < node.data) {return search(node.left, data);} else {return search(node.right, data);}}```2. 在二叉搜索树中查找节点:```javapublic TreeNode search(TreeNode node, int data) {if (node == null) {return null;}if (data == node.data) {return node;} else if (data < node.data) {return search(node.left, data);} else {return search(node.right, data);}}```六、树的应用1. 堆排序:利用二叉堆的属性,实现高效排序。
数据结构树的实验报告
数据结构实验报告目的要求1.掌握二叉树的存储实现。
2.掌握二叉树的遍历思想。
3.掌握二叉树的常见算法的程序实现。
实验内容1.输入字符序列,建立二叉链表。
2.中序遍历二叉树:递归算法。
3.中序遍历二叉树:非递归算法。
(最好也能实现先序,后序非递归算法)4.求二叉树的高度。
5.求二叉树的叶子个数。
6.借助队列实现二叉树的层次遍历。
7.在主函数中设计一个简单的菜单,分别调试上述算法。
源程序:1.头文件:栈和队列stack#include <stdio.h>#include <stdlib.h>#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0#define OVERFLOW -2typedef char TElemType;typedef struct BiTNode{ TElemType data;struct BiTNode *lchild,*rchild;}BiTNode,*BiTree;typedef BiTree SElemType;typedef BiTree QElemType;typedef BiTree Status;typedef struct Node{ //链栈的定义SElemType data;struct Node *next;}NODE;typedef struct{NODE *top;//链式栈的栈顶指针}Stack;//链式栈的操作示例void InitStack(Stack &S){S.top=(NODE *)malloc(sizeof(NODE));if (!S.top)exit(OVERFLOW);// 分配失败S.top->next=NULL;}int StackEmpty(Stack S){if (S.top->next==NULL) return(TRUE);else return(FALSE);}void Push(Stack &S,SElemType e){NODE *p;p=(NODE *)malloc(sizeof(NODE));if (!p)exit(OVERFLOW); // 分配失败p->data=e;p->next=S.top->next;S.top->next=p;}void Pop(Stack &S,SElemType &e){NODE *p;if (StackEmpty(S)) return;//栈空else {p=S.top->next;e=p->data;S.top->next=p->next;free(p);}}//队的操作typedef struct QNode{QElemType data;struct QNode *next;}QNode,*QueuePtr;typedef struct {QueuePtr front;QueuePtr rear;}LinkQueue;void InitQueue(LinkQueue &Q){ //初始化队列Q.front =Q.rear =(QueuePtr)malloc(sizeof(QNode));if(!Q.front) exit(OVERFLOW); //存储分配失败Q.front ->next =NULL;}int EnQueue(LinkQueue &Q,QElemType e) //插入元素e为Q的新的队尾元素{QueuePtr p;p=(QueuePtr)malloc(sizeof(QNode));if(!p) exit(OVERFLOW);p->data=e;p->next=NULL;Q.rear->next=p;Q.rear =p;return OK;}int DeQueue(LinkQueue &Q,QElemType &e) //删除Q的队头元素,用e返回其值{if(Q.front ==Q.rear ) return ERROR;QueuePtr p;p=Q.front ->next;e=p->data;Q.front->next=p->next ;if(Q.rear==p) Q.rear =Q.front ;free(p);return OK;}2.主程序#include <stdio.h>#include <stdlib.h>#include "math.h"#include "stack.h"int h=0,max=0,flag=0; //全局变量void CreateBiTree(BiTree &T){TElemType ch;scanf("%c",&ch);if (ch==' ') T=NULL;else{T=(BiTree)malloc(sizeof(BiTNode));T->data=ch;CreateBiTree(T->lchild);CreateBiTree(T->rchild);}}//2.中序遍历二叉树:递归算法。
数据结构实验报告
数据结构实验报告本次数据结构实验的主要内容是关于树的相关操作,包括树的创建、遍历、查找等。
通过实验,我们将对树的基本概念和操作进行深入了解,并掌握相关算法的实现和应用。
首先,我们将介绍树的创建和基本操作。
树是一种非线性数据结构,由节点和边组成,具有层次关系。
在实验中,我们通过数组和链表两种方式来创建树。
数组表示法是将树的节点按照从上到下、从左到右的顺序存储在一维数组中,通过计算节点的下标来实现对树的操作。
链表表示法则是利用指针来表示节点之间的关系,实现树的各种操作。
在创建树的过程中,我们需要考虑节点的插入、删除和修改等操作,以及树的遍历方式,包括前序遍历、中序遍历和后序遍历。
其次,我们将介绍树的查找操作。
在实际应用中,我们经常需要对树进行查找操作,以找到特定的节点或者进行相关的数据处理。
在本次实验中,我们将学习如何实现对树的查找操作,包括深度优先搜索(DFS)和广度优先搜索(BFS)两种方式。
通过这些查找算法,我们可以高效地找到树中的特定节点,并进行相应的处理。
最后,我们将进行树的应用实例分析。
树作为一种重要的数据结构,在实际应用中有着广泛的应用。
我们将通过实例分析,介绍树在各种领域的应用,包括文件系统、数据库索引、网络路由等方面。
通过这些实例,我们可以更好地理解树的重要性和实际应用。
总之,本次数据结构实验涉及了树的创建、遍历、查找和应用等方面,通过实验,我们将对树的相关概念和操作有更深入的理解,并掌握相关算法的实现和应用。
希望通过本次实验,能够对数据结构有更深入的认识,为今后的学习和应用打下良好的基础。
数据结构树的实验报告
数据结构树的实验报告数据结构树的实验报告引言:数据结构是计算机科学中的重要基础,它涉及到如何组织和存储数据以便有效地使用。
树是一种常见的数据结构,它具有层次结构和分支特征,被广泛应用于各个领域。
本实验旨在通过实践操作和观察,深入理解树的特性和应用。
一、实验目的本实验的目的是通过实践操作,掌握树的基本概念、特性和常见操作。
具体目标包括:1. 了解树的基本概念和术语;2. 掌握树的构建和遍历方法;3. 理解树的应用场景和相关算法。
二、实验过程1. 树的构建在本实验中,我们使用Python编程语言实现了树的构建。
首先,我们定义了树的节点类,节点包含一个值和指向子节点的指针。
然后,我们通过递归的方式构建了一棵树,树的每个节点都可以有多个子节点。
2. 树的遍历树的遍历是指按照一定的顺序访问树的所有节点。
在本实验中,我们实现了树的三种遍历方式:前序遍历、中序遍历和后序遍历。
前序遍历是先访问根节点,然后依次递归遍历左子树和右子树;中序遍历是先递归遍历左子树,然后访问根节点,最后递归遍历右子树;后序遍历是先递归遍历左子树和右子树,最后访问根节点。
3. 树的应用树作为一种重要的数据结构,在实际应用中有着广泛的应用。
在本实验中,我们选择了两个常见的树的应用场景进行了实践操作。
(1)文件系统文件系统可以看作是一棵树,根目录为根节点,各级子目录和文件为子节点。
通过实践操作,我们可以模拟文件系统的创建、删除、查找等操作,加深对树的理解。
(2)家谱家谱也可以看作是一棵树,根节点为家族的祖先,各级子节点为后代。
通过实践操作,我们可以实现家谱的构建、查询和修改,了解家谱的组织和维护方式。
三、实验结果与分析通过实验操作,我们成功构建了树的数据结构,并实现了树的遍历和应用。
在文件系统的实践中,我们能够灵活地创建、删除和查找文件和目录,实现了对文件系统的基本操作。
在家谱的实践中,我们能够方便地构建和查询家族成员的关系,加深了对家谱的理解。
数据结构实验报告-树(二叉树)
实验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. 实验目的1. 掌握树的定义、基本概念和基本操作;2. 学习树的构建和遍历算法;3. 了解树在实际应用中的应用。
2. 实验设备和材料- 计算机- 编程环境:Python、Java或其他编程语言3. 实验方法1. 学习树的定义、基本概念和基本操作;2. 根据给定的数据,构建一棵树;3. 实现树的遍历算法,包括前序遍历、中序遍历和后序遍历;4. 实现树的查找操作;5. 进行实验结果的验证和分析。
4. 实验过程1. 根据给定数据构建一棵树。
我们选取一个文本文件作为输入,文件中每一行代表一个节点,并用空格分隔节点和其父节点。
根据这些信息,可以构建一棵树。
2. 实现树的建立操作,通过读取文本文件,逐行构建树的节点,并将节点关系保存在合适的数据结构中。
3. 实现树的遍历算法。
我们选择实现前序遍历、中序遍历和后序遍历算法。
通过递归方式,对树进行遍历,并将结果输出。
4. 实现树的查找操作。
给定一个节点值,通过遍历树,找到并输出对应的节点。
5. 实验结果1. 根据给定数据,构建了一棵树。
树的结构如下所示:A/ \B C/ \ / \D E F G2. 实现了树的遍历算法,结果如下:- 前序遍历结果:A -> B -> D -> E -> C -> F -> G- 中序遍历结果:D -> B -> E -> A -> F -> C -> G- 后序遍历结果:D -> E -> B -> F -> G -> C -> A3. 实现了树的查找操作。
通过给定节点值,可以找到对应的节点。
数据结构-树的实现实验报告
数据结构-树的实现实验报告数据结构-树的实现实验报告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. 常见树的实现方式3. 二叉树及其操作4. 树的遍历算法5. 树在排序和搜索中的应用6. 树在图算法中的应用实验步骤与结果1. 树结构的定义和特点树是一种非线性的数据结构,由节点和边组成。
一个节点可以有多个子节点,但每个节点只有一个父节点。
树具有以下特点:- 树中只有一个根节点,它没有父节点。
- 每个非根节点有且只有一个父节点。
- 除了根节点外,每个节点可以有零个或多个子节点。
- 节点之间通过边连接。
2. 常见树的实现方式树可以通过链表或数组两种方式进行实现。
链表实现的树称为链式树,数组实现的树称为顺序树。
链式树的节点是通过指针进行连接的,每个节点包含数据和指向子节点的指针。
链式树的优点是插入和删除节点方便,缺点是访问节点需要遍历链表。
顺序树将节点存储在一个数组中,通过计算索引值来访问对应位置的节点。
顺序树的优点是访问节点快速,缺点是插入和删除节点困难。
3. 二叉树及其操作二叉树是一种特殊的树结构,每个节点最多有两个子节点。
二叉树的操作包括插入节点、删除节点、查找节点等。
二叉树的插入节点操作如下:1. 如果树为空,则将新节点作为根节点。
2. 如果新节点的值小于当前节点的值,则将新节点插入到当前节点的左子树中。
3. 如果新节点的值大于当前节点的值,则将新节点插入到当前节点的右子树中。
二叉树的删除节点操作如下:1. 如果要删除的节点是叶子节点,则直接删除它。
2. 如果要删除的节点只有一个子节点,则将子节点替代要删除的节点。
3. 如果要删除的节点有两个子节点,则将它的后继节点替代要删除的节点。
4. 树的遍历算法树的遍历算法包括先序遍历、中序遍历和后序遍历。
先序遍历按照根节点、左子树、右子树的顺序遍历树。
中序遍历按照左子树、根节点、右子树的顺序遍历树。
后序遍历按照左子树、右子树、根节点的顺序遍历树。
数据结构——树和森林实验报告
树和森林应用实验实验报告实验目的(1) 掌握树和森林的二叉链表表示方法。
(2) 掌握树和二叉树的结构及算法之间的对应关系。
(3) 掌握树的两种遍历算法及其应用。
实验运行环境Visual C++实验任务为使实验程序简洁直观,下面的部分实验程序中的一些功能实现仍以调用库函数程序"trees.h"中的函数的形式给出,并假设该库函数中定义了树指针和结点类型分别为tree和tn ode,以及部分常用运算,例如构建树(森林)、以某种方式显示树和森林等。
各运算的名称较为直观,因而易于理解。
读者可自行设计自己的库函数,也可到作者的网站下载。
说明2 :为便于数据的描述,和前面的实验一样,将测试数据结构列出,并以一个文件名的形式给出标注,例如测试数据名为treel.tre的树,其具体结构形式参见附录中的树列表中的标有treel.tre的树。
实验内容第一题:<1>将一棵树(或森林)转换为二叉树。
实验测试数据基本要求:第一组数据:tree1.tre第二组数据:tree2.tre实验准备:用广义表来表示树的数据,保存到文件中,通过文件流来读入数据,并根据读入的数据来创建树第二题:<2>求森林的高度。
实验测试数据基本要求:第一组数据:treel.tre第二组数据:tree2.tre第一组数据:full41.cbt第二组数据:letter.cbt实验准备:遍历每一棵树,寻找高度的最大值。
可以设立一个私有成员来记录数的高度。
第三题:<3>按层次方式遍历森林。
实验测试数据基本要求:第一组数据:treel.tre第二组数据:tree2.tre实验准备:先访问第一层结点,并将它放入队列中,并反复从队列中取结点,访问其孩子结点,直至访问到叶子结点。
第四题:<4>输出一个森林中每个结点的值及其对应的层次数。
实验测试数据基本要求:第一组数据:treel.tre第二组数据:tree2.tre实验准备:使用递归函数来访问森林,同时输出层次数及结点值,使用形参来传递当前层次数第五题:<5>输出一个森林的广义表形式,如下图中的森林的输出为:(a(b(c,d,e,f), g(h,i,j), k(l,m,n)),o(p(q)),r(s(t(u)), v(w(x,y,z))))实验测试数据基本要求:第一组数据:tree1.tre第二组数据:tree2.tre实验准备:使用递归函数调用,若当前节点有左孩子,则先输出‘(’再访问下一节点, 若当前节点的右指针不为空,则先输出‘,‘再访问下一结点。
树的操作及应用实验报告
树的操作及应用实验报告实验名称:树的操作及应用实验报告摘要:本实验旨在通过实际操作掌握树的基本操作,并对树的应用进行实现和分析。
实验主要包括创建树、遍历树、搜索树和删除树等操作,并应用树的特点解决实际问题。
一、引言树是一种非线性的数据结构,由若干个节点组成,节点之间通过边连接。
树的基本概念包括根节点、子节点、父节点、叶节点等。
树具有分支结构,适用于描述具有层次关系的实际问题。
二、目的1. 理解树的基本概念和操作。
2. 掌握树的遍历操作。
3. 了解搜索树的特点和应用。
4. 熟悉树的删除操作。
三、实验设备和材料1. 计算机。
2. 编程语言:C++。
四、实验步骤与结果1. 创建树:通过定义节点结构和树结构,使用代码创建树,并初始化树的根节点。
2. 遍历树:实现树的前序遍历、中序遍历和后序遍历。
通过调用递归函数,遍历树的所有节点,并将节点值输出。
3. 搜索树:实现二叉搜索树,并应用搜索树的特性进行搜索操作。
首先,通过插入节点操作创建一棵二叉搜索树。
然后,通过比较搜索值与节点值的大小,逐步定位搜索值所在的位置。
最后,输出搜索结果。
4. 删除树:实现树的删除操作。
通过递归调用函数,将树的每个节点依次删除,并释放内存。
五、实验结果分析1. 创建树的操作能够成功地创建一棵树,并初始化根节点。
2. 遍历树的操作能够按照前序、中序和后序的顺序遍历所有节点,并正确输出节点值。
3. 搜索树的操作能够根据搜索值的大小,快速地定位并输出搜索结果。
4. 删除树的操作能够依次删除树的每个节点,并及时释放内存。
六、实验结论通过本实验,我们掌握了树的基本操作,并应用树的特点解决了实际问题。
树作为一种非线性数据结构,具有广泛的应用价值,在算法和数据处理中发挥着重要作用。
七、实验感想通过本次实验,我们深入理解了树的结构和操作,并学会了如何应用树来解决实际问题。
树的递归结构使得其遍历和搜索操作非常高效,能够快速地定位和处理数据。
同时,树的删除操作也需要特别小心,避免出现内存泄漏等问题。
数据结构哈夫曼树实验报告
数据结构哈夫曼树实验报告一、实验目的本次实验的主要目的是深入理解和掌握哈夫曼树的数据结构及其相关算法,并通过实际编程实现来提高对数据结构的应用能力和编程技能。
二、实验环境本次实验使用的编程环境为具体编程语言名称,操作系统为具体操作系统名称。
三、实验原理哈夫曼树,又称最优二叉树,是一种带权路径长度最短的二叉树。
其基本原理是通过构建一棵二叉树,使得权值较大的节点距离根节点较近,权值较小的节点距离根节点较远,从而达到带权路径长度最小的目的。
在构建哈夫曼树的过程中,首先需要将所有的节点按照权值从小到大进行排序。
然后,选取权值最小的两个节点作为左右子树,构建一个新的父节点,该父节点的权值为左右子节点权值之和。
重复这个过程,直到所有的节点都被构建到哈夫曼树中。
哈夫曼编码是基于哈夫曼树的一种编码方式。
对于每个叶子节点,从根节点到该叶子节点的路径上,向左的分支编码为 0,向右的分支编码为 1,这样就可以得到每个叶子节点的哈夫曼编码。
四、实验步骤1、定义节点结构体```ctypedef struct HuffmanNode {char data;int weight;struct HuffmanNode left;struct HuffmanNode right;} HuffmanNode;```2、实现节点排序函数```cvoid sortNodes(HuffmanNode nodes, int n) {for (int i = 0; i < n 1; i++){for (int j = 0; j < n i 1; j++){if (nodesj>weight > nodesj + 1>weight) {HuffmanNode temp = nodesj;nodesj = nodesj + 1;nodesj + 1 = temp;}}}}```3、构建哈夫曼树```cHuffmanNode buildHuffmanTree(HuffmanNode nodes, int n) {while (n > 1) {sortNodes(nodes, n);HuffmanNode left = nodes0;HuffmanNode right = nodes1;HuffmanNode parent =(HuffmanNode )malloc(sizeof(HuffmanNode));parent>data ='\0';parent>weight = left>weight + right>weight;parent>left = left;parent>right = right;nodes0 = parent;nodes1 = nodesn 1;n;}return nodes0;}```4、生成哈夫曼编码```cvoid generateHuffmanCodes(HuffmanNode root, int codes, int index) {if (root>left) {codesindex = 0;generateHuffmanCodes(root>left, codes, index + 1);}if (root>right) {codesindex = 1;generateHuffmanCodes(root>right, codes, index + 1);}if (!root>left &&!root>right) {printf("%c: ", root>data);for (int i = 0; i < index; i++){printf("%d", codesi);}printf("\n");}}```5、主函数```cint main(){HuffmanNode nodes5 ={(HuffmanNode )malloc(sizeof(HuffmanNode)),(HuffmanNode )malloc(sizeof(HuffmanNode)),(HuffmanNode )malloc(sizeof(HuffmanNode)),(HuffmanNode )malloc(sizeof(HuffmanNode)),(HuffmanNode )malloc(sizeof(HuffmanNode))};nodes0>data ='A';nodes0>weight = 5;nodes1>data ='B';nodes1>weight = 9;nodes2>data ='C';nodes2>weight = 12;nodes3>data ='D';nodes3>weight = 13;nodes4>data ='E';nodes4>weight = 16;HuffmanNode root = buildHuffmanTree(nodes, 5);int codes100;generateHuffmanCodes(root, codes, 0);return 0;}```五、实验结果与分析通过运行上述程序,得到了每个字符的哈夫曼编码:A: 00B: 01C: 10D: 110E: 111分析实验结果可以发现,权值较小的字符A 和B 对应的编码较短,而权值较大的字符D 和E 对应的编码较长。
数据结构实验报告树形数据结构实验(1)
实验报告书课程名:数据结构题目:树形数据结构实验(1)班级:学号:姓名:一、目的与要求1)熟练掌握二叉树的二叉链表表示创建算法与实现;2)熟练掌握栈的前序、中序和后序递归遍历算法与实现;3)熟练掌握前序、中序和后序遍历线索二叉树的基本算法与实现;4)按照实验题目要求独立正确地完成实验内容(提交程序清单及相关实验数据与运行结果);5)认真书写实验报告,并按时提交。
二、实验内容或题目1) 创建二叉树:广义表式创建和先序创建;2) 遍历二叉树:先,中,后,层序遍历,广义表式遍历,凹凸式遍历;3) 二叉树属性:深度,宽度,结点数,叶子结点数4) 二叉树路径:叶子结点到根结点的路径;5)二叉树线索:中序线索二叉树;6)二叉树置空:清空二叉树。
三、实验步骤与源程序1)头文件Btree.h#include <iostream.h>#include <iomanip.h>#include <stdio.h>#include <stdlib.h>#include <time.h>/**********************************对象--二叉数**************** ****************/ typedef char ElemType; // 定义元素类型#define MAXSIZE 100 // 确定二叉树的最大结点数/******************************二叉数的结点类定义******************************/ class BTreeNode{private:int ltag,rtag; // 线索标记BTreeNode *left; // 左子树指针BTreeNode *right; // 右子树指针public:ElemType data; // 数据域// 构造函数BTreeNode(){ltag=0;rtag=0;left=NULL;right=NULL;}BTreeNode(ElemType item,int ltag1,int rtag1,BTreeNode *left1,BTreeNode *right1) {data=item;ltag=ltag1;rtag=rtag1;left=left1;right=right1;}BTreeNode *&Left() // 返回结点的左孩子{return left;}// 返回结点的右孩子BTreeNode *&Right(){return right;}friend class BinaryTree; // 二叉树类为二叉树结点类的友元类};/**********************************二叉数的类定义*******************************/class BinaryTree{private:BTreeNode *root;public://构造函数.初始化二叉树为空BinaryTree() { root=NULL; }// 判断二叉树是否为空bool BTreeEmpty() { return root==NULL; }/****************************创建二叉数的相关成员函数***********************/// 按照二叉树的广义表表示创建二叉树void CreateBTree1();// 递归创建二叉树,被函数CreateBTree1调用void Create1(BTreeNode *&BT);// 按一定次序输入二叉树中结点的值(一个字符),空格表示空树void CreateBTree2(int make);// 递归先序创建二叉树,被函数CreateBTree2调用void Greate2(BTreeNode*&BT,int mark);// 复制二叉树void BTreeCopy(BTreeNode *&root,BTreeNode *&BT);// 按任一种遍历次序输出二叉树中的所有结点void TraverseBTree(int mark);// 用于遍历的递归函数,被函数TraverseBTree调用void Traverse(BTreeNode *&BT,int mark);// 先序遍历的递归函数void PreOrder(BTreeNode *&BT);// 先序遍历的非递归函数一void PreOrder_N1(BTreeNode *&BT);// 先序遍历的非递归函数二void PreOrder_N2(BTreeNode *&BT);// 中序遍历的递归函数void InOrder(BTreeNode *&BT);// 中序遍历的非递归函数一void InOrder_N1(BTreeNode *&BT);// 中序遍历的非递归函数二void InOrder_N2(BTreeNode *&BT);// 后序遍历的递归函数void PostOrder(BTreeNode *&BT);// 后序遍历的非递归函数一void PostOrder_N1(BTreeNode *&BT);// 后序遍历的递归函数void PostOrder_N2(BTreeNode *&BT);// 层序遍历的非递归函数void LayerOrder(BTreeNode *&BT);// 按照二叉树的广义表表示输出整个二叉树void GPrintBTree();// 广义表形式输出整个二叉树的递归函数,被函数Print调用void GPrint(BTreeNode *&BT);// 以凹凸表示法输出二叉树void OPrintTree();/**********************************二叉树的属性*****************************/ /****************计算二叉数深度,宽度,叶子,结点的相关成员函数****************/// 求二叉树的深度int BTreeDepth();// 用于求二叉树深度的递归函数,被BTreeDepth调用int Depth(BTreeNode *&BT);// 求二叉树的宽度int BTreeWidth();// 求二叉树中所有结点数int BTreeCount();// 用于求二叉树所有结点数的递归函数,被函数BTreeCount调用int Count(BTreeNode *&BT);int BTreeLeafCount();// 用于求二叉树中所有叶子结点数的递归函数,被函数BTreeLeafCount调用int LeafCount(BTreeNode *&BT);// 输出二叉树的所有叶子结点void BTreeLeafPrint();// 用于输出二叉树的所有叶子结点的递归函数,被函数BTreeLeafPrint调用void LeafPrint(BTreeNode *&BT);/***********************二叉树中从根结点到叶子结点的路径相关函数****************/// 输出从根结点到叶子结点的路径,以及最长路径void BTreePath();// 输出从根结点到叶子结点的路径的递归函数,被函数BTreePath调用void PathLeaf(BTreeNode *&BT,ElemType path[],int pathlen);// 求最长路径的递归函数,被函数BTreePaht调用void BTreeLongpath(BTreeNode *&BT,ElemType path[],int pathlen,ElemType longpath[],int &longpathlen);// 非递归方法输出从根结点到叶子结点的路径void BTreePath_N1();// 返回data域为x的结点指针void BTreeFind(ElemType x);// 返回data域为x的结点指针的递归函数,被函数BTreeFind调用BTreeNode *FindNode(BTreeNode *&BT,ElemType x);/*************************************线索二叉树****************************/// 线索化二叉树void CreateThread();// 中序线索化二叉树的递归函数,被函数CreateThread调用void InOrderThread(BTreeNode *&BT,BTreeNode *&pre);// 中序线索化二叉树中实现中序遍历,被函数CreateThread调用void ThInOrder(BTreeNode *&BT);/****************************销毁二叉数的相关成员函数***********************/// 置空二叉树void BTreeClear();// 用于清除二叉树的递归函数,被函数BTreeClear和~BinaryTree调用void Clear(BTreeNode *&BT);// 析构函数,清除二叉树~BinaryTree();};/******************************创建二叉数的相关成员函数*************************/void BinaryTree::CreateBTree1(){cout<<"输入广义表形式的二叉树:"<<endl;root=NULL; // 给树根指针置空Create1(root);}// 递归创建二叉树,被函数CreateBTree1调用void BinaryTree::Create1(BTreeNode *&BT){ BTreeNode *stack[MAXSIZE],*p=NULL;int k,top=-1;char ch;while((ch=getchar())!='#'){switch(ch){case '(':top++;stack[top]=p;k=1; // 即将建立左结点break;case ')':top--;break;case ',':k=2; // 即将建立右结点break;default:if(!(p=new BTreeNode)){cout<<"\n堆内存分配失败\n";exit(1);}p->data=ch;p->left=p->right=NULL;if(BT==NULL) // p指向二叉树的根结点,建立根结点BT=p;else // 已经建立根结点{if(k==1) // 建立左结点stack[top]->left=p;else // 建立右结点stack[top]->right=p;}}//switch(ch)}// 按一定次序输入二叉树中结点的值(一个字符),空格表示空树void BinaryTree::CreateBTree2(int mark){switch(mark){case 1:puts("按先序输入二叉树:");break;case 2:puts("按中序输入二叉树:");break;case 3:puts("按后序输入二叉树:");break;}root=NULL; // 给树根指针置空BTreeNode *&p=root; // 定义p为指向二叉树结点的指针Greate2(p,mark);}// 递归创建二叉树,被函数CreateBTree2调用void BinaryTree::Greate2(BTreeNode *&BT,int mark){char ch;ch=getchar();switch(mark){case 1: // 先序创建if(ch==' ')BT=NULL;else{if(!(BT=new BTreeNode)){cout<<"\n堆内存分配失败\n";exit(1);}BT->data=ch;Greate2(BT->left,mark);Greate2(BT->right,mark);}break;case 2:break;break;}}// 复制二叉树void BinaryTree::BTreeCopy(BTreeNode *&root,BTreeNode *&BT){if(root){if(!(BT=new BTreeNode)){exit(1);}BT->data=root->data;BTreeCopy(root->left,BT->left);BTreeCopy(root->right,BT->right);}elseBT=NULL;}/*******************************遍历二叉数的相关成员函数************************/// 按任一种遍历次序输出二叉树中的所有结点void BinaryTree::TraverseBTree(int mark){srand(time(NULL)); // 产生随机种子数,用来选择相同顺序遍历的不同算法Traverse(root,mark);cout<<endl;}// 用于遍历的递归函数,被函数TraverseBTree调用void BinaryTree::Traverse(BTreeNode *&BT,int mark){int option;switch(mark){case 1: // 先序遍历{option=rand()%3+1;switch(option) // 随机选择一种先序算法{case 1:PreOrder(BT);break;case 2:break;case 3:PreOrder_N2(BT);break;}break;}case 2: // 中序遍历{option = rand()%3 + 1;switch(option) // 随机选择一种中序算法{case 1:InOrder(BT);break;case 2:InOrder_N1(BT);break;case 3:InOrder_N2(BT);break;}break;}case 3: // 后序遍历{option=rand()%3+1;switch(option) // 随机选择一种先序算法{case 1:PostOrder(BT);break;case 2:PostOrder_N1(BT);break;case 3:PostOrder_N2(BT);break;}break;}case 4: // 层序遍历{LayerOrder(BT);break;default:cout<<"mark的值无效!遍历失败!"<<endl;}}// 先序遍历的递归函数void BinaryTree::PreOrder(BTreeNode *&BT){if(BT!=NULL){cout<<BT->data<<' ';PreOrder(BT->left);PreOrder(BT->right);}}// 先序遍历的非递归函数一void BinaryTree::PreOrder_N1(BTreeNode *&BT){BTreeNode *p;struct{BTreeNode *pt;int tag;}stack[MAXSIZE];int top=-1;top++;stack[top].pt=BT;stack[top].tag=1;while(top>-1) // 栈不空时循环{if(stack[top].tag==1) // 不能直接访问{p=stack[top].pt;top--;if(p!=NULL) // 按右,左,结点顺序进栈,后进先出,即先序遍历{top++;stack[top].pt=p->right; // 右孩子入栈stack[top].tag=1;top++;stack[top].pt=p->left; // 左孩子入栈stack[top].tag=1;top++;stack[top].pt=p; // 根结点入栈}}if(stack[top].tag==0) // 可以直接访问{cout<<stack[top].pt->data<<' ';top--;}}}// 先序遍历的非递归函数二void BinaryTree::PreOrder_N2(BTreeNode *&BT) {BTreeNode *stack[MAXSIZE],*p;int top = -1;if(BT!=NULL){top++; // 根结点入栈stack[top] = BT;while(top>-1) // 栈不空时循环{p=stack[top];top--;cout<<p->data<<" ";if(p->right != NULL) // 右孩子入栈{top++;stack[top] = p->right;}if(p->left != NULL) // 左孩子入栈{top++;stack[top] = p->left;}}//while}//if(root!=NULL)}// 中序遍历的递归函数void BinaryTree::InOrder(BTreeNode *&BT) {if(BT!=NULL){InOrder(BT->left);cout<<BT->data<<' ';InOrder(BT->right);}// 中序遍历的非递归函数一void BinaryTree::InOrder_N1(BTreeNode *&BT){BTreeNode *p;struct{BTreeNode *pt;int tag;}stack[MAXSIZE];int top = -1;top++;stack[top].pt = BT;stack[top].tag = 1;while(top>-1) // 栈不空时循环{if(stack[top].tag == 1) // 不能直接访问{p = stack[top].pt;top--;if(p!=NULL) // 按右,左,结点顺序进栈,后进先出,即先序遍历{top++;stack[top].pt=p->right; // 右孩子入栈stack[top].tag = 1;top++;stack[top].pt = p; // 根结点入栈stack[top].tag = 0; // 可以直接访问top++;stack[top].pt =p->left; // 左孩子入栈stack[top].tag = 1;}}if(stack[top].tag == 0) // 可以直接访问{cout<<stack[top].pt->data<<' ';top--;}}}// 中序遍历的非递归函数二void BinaryTree::InOrder_N2(BTreeNode *&BT)BTreeNode *stack[MAXSIZE],*p;int top = -1;if(BT != NULL){p = BT;while(top > -1||p != NULL){while(p != NULL) // 所有左结点入栈{top++;stack[top] = p;p = p->left;}if(top > -1){p = stack[top];top--;cout<<p->data<<" ";p = p->right;}}}//if}// 后序遍历的递归函数void BinaryTree::PostOrder(BTreeNode *&BT) {if(BT!=NULL){PostOrder(BT->left);PostOrder(BT->right);cout<<BT->data<<' ';}}// 后序遍历的非递归函数一void BinaryTree::PostOrder_N1(BTreeNode *&BT) {BTreeNode *p;struct{BTreeNode *pt;int tag;}stack[MAXSIZE];int top = -1;top++;stack[top].pt = BT;stack[top].tag = 1;while(top>-1) // 栈不空时循环{if(stack[top].tag == 1) // 不能直接访问{p = stack[top].pt;top--;if(p!=NULL) // 按右,左,结点顺序进栈,后进先出,即先序遍历{top++;stack[top].pt = p; // 根结点入栈stack[top].tag = 0; // 可以直接访问top++;stack[top].pt=p->right; // 右孩子入栈stack[top].tag = 1;top++;stack[top].pt =p->left; // 左孩子入栈stack[top].tag = 1;}}if(stack[top].tag == 0) // 可以直接访问{cout<<stack[top].pt->data<<' ';top--;}}}// 后序遍历的非递归函数二void BinaryTree::PostOrder_N2(BTreeNode *&BT){BTreeNode *stack[MAXSIZE],*p,*q;q=BT;int top = -1,flag;if(q != NULL){do{while(q != NULL) // 所有左结点入栈{top++;stack[top] = q;q = q->left;}p=NULL; // p指向当前结点的前一个已访问的结点flag=1; // 设置q的访问标记为已访问过while(top > -1&&flag){q = stack[top]; // 取出当前栈顶元素if(q->right == p) // 当右孩子不存在或已被访问时,则访问{cout<<q->data<<" ";top--;p = q; // p指向刚被访问的结点}else{q = q->right; // 指向右孩子flag = 0; // 设置未被访问的标记}}}while(top>-1);}//if}// 层序遍历的非递归函数void BinaryTree::LayerOrder(BTreeNode *&BT){BTreeNode *Queue[MAXSIZE]; // 定义存储二叉树结点指针的数组空间作为队列使用int front=0,rear=0; // 定义队首指针和队尾指针,初始均置0表示空队BTreeNode *p;if(BT!=NULL){rear=(rear+1)%MAXSIZE; // 后移队尾指针Queue[rear]=BT; // 将树根结点指针进队}while(front!=rear) // 当队列非空时执行循环{front=(front+1)%MAXSIZE; // 后移队首指针p=Queue[front]; // 删除队首结点的值cout<<p->data<<' '; // 输出队首结点的值if(p->left!=NULL) // 若结点存在左孩子,则左孩子结点指针进队{rear=(rear+1)%MAXSIZE;Queue[rear]=p->left;}if(p->right!=NULL) // 若结点存在右孩子,则右孩子结点指针进队{rear=(rear+1)%MAXSIZE;Queue[rear]=p->right;}}}// 按照二叉树的广义表表示输出整个二叉树void BinaryTree::GPrintBTree(){GPrint(root);cout<<endl;}// 广义表形式输出整个二叉树的递归函数,被函数Print调用void BinaryTree::GPrint(BTreeNode *&BT){if(BT==NULL)return; // 树为空时返回else // 否则执行如下操作{cout<<BT->data; // 输出根结点的值if(BT->left!=NULL||BT->right!=NULL){cout<<'('; // 输出左括号GPrint(BT->left); // 输出左子树if(BT->right!=NULL)cout<<','; // 若右子树不为空则输出逗号分隔符GPrint(BT->right); // 输出右子树cout<<')'; // 输出右括号}}}// 以凹凸表示法输出二叉树void BinaryTree::OPrintTree(){cout<<endl;BTreeNode *stack[MAXSIZE],*p;int level[MAXSIZE][2],top=-1,n,i,width=4;int maxwidth=40;char type[20];char *pre_type=type;if(root!=NULL){top++; // 根结点入栈stack[top]=root;level[top][0]=width;level[top][1]=2; // 2表示是根while(top>-1){p=stack[top]; // 退栈并凹入显示该结点值n=level[top][0];switch(level[top][1]){case 0:pre_type="左结点";break;case 1:pre_type="右结点";break;case 2:pre_type="根结点";}for(i=1;i<=n;i++) // n为显示场宽,字符以右对齐显示cout<<" ";cout<<" "<<p->data<<"("<<pre_type<<")";for(i=n+1;i<=maxwidth;i+=2)cout<<"--";cout<<endl;top--;if(p->right!=NULL){top++; // 将右子树树根结点入栈stack[top]=p->right;level[top][0]=n+width; // 显示场宽增加widthlevel[top][1]=1; // 1表示右子树}if(p->left!=NULL){top++; // 将左子树树根结点入栈stack[top]=p->left;level[top][0]=n+width; // 显示场宽增加widthlevel[top][1]=0; // 0表示左子树}}//while}//if}/******************计算二叉数深度,宽度,叶子,结点的相关成员函数******************/// 求二叉树的深度int BinaryTree::BTreeDepth(){return Depth(root);}// 用于求二叉树深度的递归函数,被BTreeDepth调用int BinaryTree::Depth(BTreeNode *&BT){if(BT==NULL)return 0; // 对于空树,返回0并结束递归else{int dep_left=Depth(BT->left); // 计算左子树的深度int dep_right=Depth(BT->right); // 计算右子树的深度if(dep_left>dep_right) // 返回树的深度return dep_left+1;elsereturn dep_right+1;}}// 求二叉树的宽度int BinaryTree::BTreeWidth(){struct Queue{int layer; // 结点的层次编号BTreeNode *p; // 结点指针}Queue[MAXSIZE]; // 定义顺序队列,存储二叉数所有的结点int front,rear;front=rear=0;int cur_layer; // 存储当前结点所在的层数BTreeNode *q=root;if(q!=NULL){rear++;Queue[rear].p=q; // 根结点指针入队Queue[rear].layer=1; // 根结点的层次编号为1while(rear!=front) // while循环通过层次遍历求每个结点的层次{front++;q=Queue[front].p; // 队头出队cur_layer=Queue[front].layer; // 当前结点所在的层数if(q->left!=NULL) // 左孩子入队{rear++;Queue[rear].p=q->left;Queue[rear].layer=cur_layer+1; // 当前结点的孩子在该结点的下一层}if(q->right!=NULL) // 右孩子入队{rear++;Queue[rear].p=q->right;Queue[rear].layer=cur_layer+1; // 当前结点的孩子在该结点的下一层}}//whileint max_layer=0,i=1,n;cur_layer=1; // 从第一层开始while(i<=rear) // 通过比较相同层次的结点数求树的深度{n=0;while(i<=rear&&Queue[i].layer==cur_layer){n++; // n累计cur_lay层中的结点层次i++;}cur_layer=Queue[i].layer; // 取下一个层次,此时Queue[i]存放下一个层次的第一个结点if(n>max_layer)max_layer=n; // 将最大层的结点树赋给max}return max_layer;}elsereturn 0;}// 求二叉树中所有结点数int BinaryTree::BTreeCount(){return Count(root);}// 用于求二叉树中所有结点数的递归函数,被函数BTreeCount调用int BinaryTree::Count(BTreeNode *&BT){if(BT==NULL)return 0;elsereturn Count(BT->left)+Count(BT->right)+1;}// 求二叉树中所有叶子结点数int BinaryTree::BTreeLeafCount(){return LeafCount(root);}// 用于求二叉树中所有叶子结点数的递归函数,被函数BTreeLeafCount调用int BinaryTree::LeafCount(BTreeNode *&BT){if(BT == NULL)return 0;else if(BT->left==NULL&&BT->right==NULL)return 1;elsereturn LeafCount(BT->left)+LeafCount(BT->right);}// 输出二叉树的所有叶子结点void BinaryTree::BTreeLeafPrint(){LeafPrint(root);}// 用于输出二叉树的所有叶子结点的递归函数,被函数BTreeLeafPrint调用void BinaryTree::LeafPrint(BTreeNode *&BT){if(BT != NULL){if(BT->left == NULL && BT->right==NULL)cout<<" "<<BT->data;else{LeafPrint(BT->left);LeafPrint(BT->right);}}}// 返回data域为x的结点指针void BinaryTree::BTreeFind(ElemType x){BTreeNode *p;p=FindNode(root,x);if(p!=NULL)cout<<" "<<x<<"在二叉树中"<<endl;elsecout<<" "<<x<<"不在二叉树中"<<endl;}// 返回data域为x的结点指针的递归函数,被函数BTreeFind调用BTreeNode *BinaryTree::FindNode(BTreeNode *&BT,ElemType x){BTreeNode *p;if(BT==NULL)return NULL;else if(BT->data==x)return BT;else{p=FindNode(BT->left,x);if(p!=NULL)return p;elsereturn FindNode(BT->right,x);}}/***********************二叉树中从根结点到叶子结点的路径相关函数****************/// 输出从根结点到叶子结点的路径,以及最长路径void BinaryTree::BTreePath(){int longpathlen=0;ElemType path[MAXSIZE],longpath[MAXSIZE];PathLeaf(root,path,0);cout<<endl;BTreeLongpath(root,path,0,longpath,longpathlen);cout<<"第一条最长为 "<<longpathlen<<" 的路径:";for(int i=longpathlen-1;i>=0;i--)cout<<" "<<longpath[i];cout<<endl;}// 输出从根结点到叶子结点的路径的递归函数,被函数BTreePath调用void BinaryTree::PathLeaf(BTreeNode *&BT,ElemType path[],int pathlen){if(BT!=NULL){if(BT->left==NULL&&BT->right==NULL) // BT为叶子结点{cout<<"叶子结点"<<BT->data<<"到根结点路径:"<<" ";cout<<BT->data<<" ";for(int i=pathlen-1;i>=0;i--)cout<<path[i]<<" ";cout<<endl;else{path[pathlen]=BT->data; // 将当前结点放入路径中pathlen++; // 路径长度加1PathLeaf(BT->left,path,pathlen); // 递归扫描左子树PathLeaf(BT->right,path,pathlen); // 递归扫描右子树pathlen--; // 恢复环境}}}// 求最长路径的递归函数,被函数BTreePaht调用void BinaryTree::BTreeLongpath(BTreeNode *&BT,ElemType path[],int pathlen,ElemType longpath[],int &longpathlen){if(BT==NULL){if(pathlen>longpathlen) // 若当前路径更长,将路径保存在longpath中{for(int i=pathlen-1;i>=0;i--)longpath[i]=path[i];longpathlen=pathlen;}}else{path[pathlen]=BT->data; // 将当前结点放入路径中pathlen++; // 路径长度加1BTreeLongpath(BT->left,path,pathlen,longpath,longpathlen); // 扫描左子树BTreeLongpath(BT->right,path,pathlen,longpath,longpathlen); // 扫描右子树pathlen--; // 恢复环境}}// 非递归方法输出从根结点到叶子结点的路径void BinaryTree::BTreePath_N1(){BTreeNode *q=root;struct{BTreeNode *pt; // 存放当前结点的指针int parent; // 存放双亲结点在队列中的位置}Queue[MAXSIZE];int front,rear,p;front=rear=-1;Queue[rear].pt=q; // 根结点入队Queue[rear].parent=-1; // 根结点没有双亲结点while(front<rear) // 队列不空{front++;q=Queue[front].pt; // 队头出队if(q->left==NULL&&q->right==NULL) // q为叶子结点{cout<<"叶子结点"<<q->data<<"到根结点路径:"<<" ";p=front;while(Queue[p].parent!=-1) // p指向根结点时退出循环{cout<<Queue[p].pt->data<<" ";p=Queue[p].parent;}cout<<Queue[p].pt->data<<endl; // 输出根结点}if(q->left!=NULL) // 左孩子入队{rear++;Queue[rear].pt=q->left;Queue[rear].parent=front;}if(q->right!=NULL) // 右孩子入队{rear++;Queue[rear].pt=q->right;Queue[rear].parent=front;}}//whilecout<<endl;}/*************************************线索二叉树********************************/// 线索化二叉树void BinaryTree::CreateThread(){BTreeNode *pre;BTreeNode *t_root;BTreeCopy(root,t_root); // 复制二叉树root给t_rootBTreeNode *throot; // 二叉线索树的头结点指针throot=new BTreeNode; // 创建二叉线索树头结点throot->ltag=0;throot->right=throot;if(root==NULL)throot->left=throot; // 空二叉树else{throot->left=t_root;pre=throot; // pre是p的前驱结点InOrderThread(t_root,pre); // 中序线索化二叉树pre->right=throot; // 最后处理,加入指向根结点的线索pre->rtag=1;throot->right=pre; // 根结点右线索化}ThInOrder(throot); // 中序线索化二叉树中实现中序遍历}// 中序线索化二叉树的递归函数,被函数CreateThread调用void BinaryTree::InOrderThread(BTreeNode *&BT,BTreeNode *&pre) {if(BT!=NULL){InOrderThread(BT->left,pre); // 左子树线索化if(BT->left==NULL) // 前驱线索{BT->left=pre; // 建立当前结点的前驱线索BT->ltag=1;}elseBT->ltag=0;if(pre->right==NULL) // 后续线索{pre->right=BT; // 建立前驱结点的后续线索pre->rtag=1;}elsepre->rtag=0;pre=BT;InOrderThread(BT->right,pre); // 右子树线索化}}// 中序线索化二叉树中实现中序遍历,被函数CreateThread调用void BinaryTree::ThInOrder(BTreeNode *&BT){BTreeNode *p=BT->left; // p指向根结点while(p->ltag==0)p=p->left;cout<<" "<<p->data; // 访问其左子树为空的结点while(p->rtag==1&&p->right!=BT){p=p->right;cout<<" "<<p->data; // 访问后续结点}p=p->right;}cout<<endl;}/******************************销毁二叉数的相关成员函数*************************/// 置空二叉树void BinaryTree::BTreeClear(){Clear(root);}// 析构函数,清除二叉树BinaryTree::~BinaryTree(){Clear(root);}// 用于清除二叉树的递归函数void BinaryTree::Clear(BTreeNode *&BT){if(BT!=NULL){// 当二叉树非空时进行如下操作Clear(BT->left); // 删除左子树Clear(BT->right); // 删除右子树delete BT; // 删除根结点BT=NULL;}}2) 源文件Btree.cpp#include "Btree.h"BinaryTree Btree;char option;int flag=0; // 标志当前二叉树是否已经创建,初始化为0,即还没有创建do{cout<<" 二叉树演示程序\n\n";if(flag==0) // 标志二叉树还没有创建cout<<"[1] 二叉树创建"<<endl;else // 标志二叉树已经创建cout<<"[1] 二叉树创建+"<<endl;cout<<"[2] 二叉树遍历"<<endl;cout<<"[3] 二叉树属性"<<endl;cout<<"[4] 二叉树路径"<<endl;cout<<"[5] 二叉树线索"<<endl;cout<<"[6] 二叉树置空"<<endl;cout<<"[7] 退出"<<endl;cout<<"1--7 请选择: ";cin>>option;cout<<endl;switch(option){case '1': // 二叉树创建{char option1;do{if(flag==0) // 标志二叉树还没有创建cout<<"二叉树创建"<<endl;else // 标志二叉树已经创建cout<<"二叉树创建+"<<endl;cout<<" "<<"[1] 广义表形式输入"<<endl;cout<<" "<<"[2] 先序式输入"<<endl;cout<<" "<<"[3] 返回主菜单"<<endl;cout<<" "<<"1--2 请选择: ";cin>>option1;cout<<endl;switch(option1){case '1': // 广义表形式输入{Btree.CreateBTree1();flag=1; // 标志二叉树已经创建cout<<"\npress any key to continue";cin.get();break;}case '2': // 先序式输入{Btree.CreateBTree2(1);flag=1; // 标志二叉树已经创建cout<<"\npress any key to continue";cin.get();cin.get();break;}case '3': // 返回主菜单break;default:cout<<"您的选择超出范围,请重新选择"<<endl;cout<<"\npress any key to continue";cin.get();cin.get();}cout<<"\n\n\n\n\n\n\n\n\n\n";}while(option1!='3');break;}case '2': // 二叉树遍历{char option2;do{cout<<"二叉树遍历"<<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<<" "<<"1--8 请选择: ";cin>>option2;cout<<endl;switch(option2){case '1': // 先序遍历{cout<<"先序遍历: ";cout<<"\npress any key to continue";cin.get();cin.get();break;}case '2': // 中序遍历{cout<<"中序遍历: ";Btree.TraverseBTree(2);cout<<"\npress any key to continue";cin.get();cin.get();break;}case '3': // 后序遍历{cout<<"后序遍历: ";Btree.TraverseBTree(3);cout<<"\npress any key to continue";cin.get();cin.get();break;}case '4': // 层序遍历{cout<<"层序遍历: ";Btree.TraverseBTree(4);cout<<"\npress any key to continue";cin.get();cin.get();break;}case '5': // 广义表式遍历{cout<<"广义表式遍历: ";Btree.GPrintBTree();cout<<"\npress any key to continue";cin.get();cin.get();break;}case '6': // 凹凸式遍历{cout<<"凹凸式遍历: ";Btree.OPrintTree();cin.get();cin.get();break;}case '7': // 查找结点{cout<<"请输入要查找的数据: ";ElemType find;cin>>find;Btree.BTreeFind(find);cout<<"\npress any key to continue";cin.get();cin.get();break;}case '8': // 返回主菜单{break;}default:cout<<"您的选择超出范围,请重新选择"<<endl;cout<<"\npress any key to continue";cin.get();cin.get();}cout<<"\n\n\n\n\n\n\n\n\n\n";}while(option2!='8');break;}case '3': // 二叉树属性{char option3;do{cout<<"二叉树属性"<<endl;cout<<" "<<"[1] 显示属性"<<endl;cout<<" "<<"[2] 返回主菜单"<<endl;cout<<" "<<"1--2 请选择: ";cin>>option3;cout<<endl;switch(option3){case '1': // 显示属性{int temp;cout<<"二叉树的深度: "<<temp<<endl;temp=Btree.BTreeWidth();cout<<"二叉树的宽度: "<<temp<<endl;temp=Btree.BTreeCount();cout<<"二叉树的结点数: "<<temp<<endl;temp=Btree.BTreeLeafCount();cout<<"二叉树的叶子数: "<<temp<<endl;cout<<"\npress any key to continue";cin.get();cin.get();break;}case '2': // 返回主菜单{break;}default:cout<<"您的选择超出范围,请重新选择"<<endl;cout<<"\npress any key to continue";cin.get();cin.get();}cout<<"\n\n\n\n\n\n\n\n\n\n";}while(option3!='2');break;}case '4': // 二叉树路径{char option4;do{cout<<"二叉树属性"<<endl;cout<<" "<<"[1] 显示叶子到根结点的路径"<<endl;cout<<" "<<"[2] 返回主菜单"<<endl;cout<<" "<<"1--2 请选择: ";cin>>option4;cout<<endl;switch(option4){case '1': // 显示叶子到根结点的路径{Btree.BTreePath();cout<<"\npress any key to continue";cin.get();cin.get();。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
delete Q.front;
Q.front=Q.rear;
}
return OK;
}
/*将Q清为空队列*/
int ClearQueue (LinkQueue &Q)
{
QueuePtr p,q;
Q.rear=Q.front;
p=Q.front->next;
Q.front->next=NULL;
InitQueue(q);
cout<<"请输入根节点,空格代表跟为空:";
int InitQueue (LinkQueue &Q)
{
if(!(Q.front=Q.rear=new QNode))
exit(OVERFLOW);
Q.front->next=NULL;
return OK;
}
/*销毁队列Q*/
int DestroyQueue(LinkQueue &Q)
{
while(Q.front){
TraverseTree(T,visit());
初始条件:树T存在,visit是对结点操作的应用函数。
操作结果:按某种次序对T的每个结点调用函数visit()一次且至多一次。一旦visit()失败,则操作失败。
CSTree Search(CSTree T,TElemType cur_e);
初始条件:树T存在,cur_e可能是树T中某一个结点的值。
#include<iostream>
#include<conio.h>
using namespace std;
const int TRUE=1;
const int FALSE=0;
const int OK=1;
const int ERROR=0;
const int OVERFLOW=1;
const int MAX=30;
typedef struct LinkQueue
{
QueuePtr front,rear; /*队头、队尾指针*/
}LinkQueue;
/*******************************队列定义**************************************/
/*构造一个空队列*/
4.设计说明
本程序采用树的二叉链表(孩子指针-兄弟指针-双亲指针)存储表示,以下是树的结构定义和基本操作:
ADT Tree{
数据对象D:D是具有相同特性的数据元素的集合。
数据关系R:
若D为空集,则称为空树;
若D仅含有一个数据元素,则R为空集,否则R={H},H是如下二元关系:
(1)在D中存在唯一的称为根的数据元素root,它在关系H下无前驱;
操作结果:在树T中查找值为cur_e的结点,找到返回指向这个结点的指针,否则返回空指针。
这个函数的作用是为了几个基本操作而服务的。
void LevelOrderTraverseTree(CSTree T,void (* visit)(TElemType));
初始条件:树T存在,visit是对结点操作的应用函数。
void visit_print(CSTree p);
初始条件:树T存在,visit_print是对结点操作的应用函数。
操作函数:对T的每一个结点调用函数visit_print()一次且至多一次。
与visit函数不一样的是,visit函数只是输出一个结点的值,而visit_print还输出其结点,第一个孩子,其右兄弟和双亲的值
const char NIL=' ';
/*****************树的二叉链表孩子-兄弟-双亲存储表示***************************/
typedef struct CSnode
{
char data;
CSnode *firstchild,*nextsibling,*parent;
LeftChild(T,cur_e);
初始条件:树T存在,cur_e是T中某个结点。
操作结果:若cur_e是T的非叶子结点,则返回它的最左孩子,否则返回“空”。
RightSibling(T,cur_e);
初始条件:树T存在,cur_e是T中某个结点。
操作结果:若cur_e有右兄弟,则返回它的右兄弟,否则返回“空”。
2.实验目的
对某个具体的抽象数据类型,运用课程所学的知识和方法,设计合理的数据结构,并在此基础上实现该抽象数据类型的全部基本操作。通过本设计性实验,检验所学知识和能力,发现学习中存在的问题。进而达到熟练地运用本课程中的基础知识及技术的目的。
3.实验环境
1、硬件:PC机
2、软件:Microsoft Visual C++ 6.0
初始条件:树T存在,cur_e是T中某个结点。
操作结果:返回cur_e的值。
Assign(T,cur_e,value);
初始条件:树T存在,cur_e是T中某个结点。
操作结果:结点cur_e赋值为value。
Parent(T,cur_e);
初始条件:树T存在,cur_e是T中某个结点。
操作结果:若cur_e是T的非根结点,则返回它的双亲,否则函数值为“空”。
InsertChild(&T,&p,I,c);
初始条件:树T存在,p指向T中某个结点,1≤i≤p指结点的度+1,非空树c与T不相交。
操作结果:插入c为T中p指结点的第i棵子树。
DeleteChild(&T,&p,i);
初始条件:树T存在,p指向T中某个结点,1≤i≤p指结点的度。
操作结果:删除T中p所指结点的第i棵子树。
(2)若D-{root}≠NULL,则存在D-{root}的一个划分D1,D2,D3,…,Dm(m>0),对于任意j≠k(1≤j,k≤m)有Dj∩Dk=NULL,且对任意的i(1≤i≤m),唯一存在数据元素xi∈Di有<root,xi>∈H;
(3)对应于D-{root}的划分,H-{<root,xi>,…,<root,xm>}有唯一的一个划分H1,H2,…,Hm(m>0),对任意j≠k(1≤j,k≤m)有Hj∩Hk=NULL,且对任意i(1≤i≤m),Hi是Di上的二元关系,(Di,{Hi})是一棵符合本定义的树,称为根root的子树。
/*最左孩子指针、下一个兄弟指针、双亲指针*/
}CSNode,*CSTree;
/********************树的辅助队列结构定义和操作******************************/
typedef struct QNode
{
CSTree data;
QNode *next;
}QNode,*QueuePtr;/*队列的单链式存储结构*/
基本操作P:
InitTree(&T);
操作结果:构造空树T。
DestroyTree(&T);
初始条件:树T存在。
操作结果:销毁树T。
CreateTree(&T,definition);
初始条件:definition给出树T的定义。
操作结果:按definition构造树T。
ClearTree(&T);
初始条件:树T存在。
操作结果:将树T清为空树。
TreeEmpty(T);
初始条件:树T存在。
操作结果:若T为空树,则返回TRUE,否则返回FALSE。
TreeDepth(T);
初始条件:树T存在。
操作结果:返回T的深度。
Root(T);
初始条件:树T存在。
操作结果:返回T的根。
Value(T,cur_e);
函数的功能实现是递归实现的。
void PostOrderTraverseTree(CSTree T,void (*visit)(TElemType));
初始条件:树T存在,visit是对结点操作的应用函数。
操作结果:按后根遍历对T的每一个结点调用函数visit()一次且至多一次。
函数的功能实现是递归实现的。
if(T->nextsibling) DestroyTree(T->nextsibling);
delete T;
}
}
/*初始条件:树T存在*/
/*操作结果:按层次次序创建树T*/
int CreateTree(CSTree &T)
{
char c[MAX];
CSTree p,p1,temp;
LinkQueue q;
返回树T的深度?
结果:4
返回树T的根结点?
结果:A
返回树F结点的值?
结果:F
将树根节点重新赋值为W ?
结果:A<—>W
求出结点A的双亲?
结果:W
求出结点A的第一个孩子结点?
结果:D
求出G的第一个兄弟结点?
结果:H
插入子树C至A中第2科子树?
结果:
删除树结点为R的第三颗子树?
结果:
多种遍历方式遍历树
前序遍历树:W-A-D-X-Y-Z-E-B
}
/*若队列不空,删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR*/
int DeQueue(LinkQueue &Q,CSTree &e)
{
QueuePtr p;
if(Q.front==Q.rear) return ERROR;
p=Q.front->next;
e=p->data;
Q.front->next=p->next;