数据结构实验五 树的基本操作
- 格式:doc
- 大小:337.50 KB
- 文档页数:6
《数据结构》树的基本操作数据结构是计算机科学中的重要概念,它是指在计算机内存中组织数据的方式。
树是一种重要的数据结构,它具有层次结构和非线性的特点。
树的基本操作包括插入、删除、和遍历。
本文将详细介绍树的基本操作。
首先,我们先了解一下树的基本概念。
树由节点和边组成,每个节点可以有多个子节点,但每个子节点只能有一个父节点。
树有一个根节点,根节点没有父节点。
除了根节点之外,每个节点都有且仅有一个父节点。
节点之间的连接称为边。
树的基本操作之一是插入操作。
插入操作是指在树中添加新节点的过程。
要插入一个节点,需要找到它的父节点,然后将父节点的子节点指针指向新节点。
插入操作的时间复杂度为O(1),因为它只需要修改指针。
另一个基本操作是删除操作。
删除操作是指将一个节点及其所有子节点从树中移除的过程。
要删除一个节点,需要找到它的父节点,然后将父节点的子节点指针指向它的子节点。
删除操作的时间复杂度取决于树的结构,通常为O(logn)到O(n)之间。
操作是树的另一个重要操作。
操作是指在树中查找一个特定节点的过程。
要一个节点,可以使用深度优先(DFS)或广度优先(BFS)算法。
DFS通过递归地遍历树的子节点,找到与目标节点相同的节点。
BFS通过遍历树的层次结构,逐层地目标节点。
操作的时间复杂度取决于树的深度,通常为O(logn)到O(n)之间。
最后,树的遍历操作是指按照一定顺序访问树中的所有节点。
常见的遍历方式有前序遍历、中序遍历和后序遍历。
前序遍历先访问根节点,然后递归地遍历左子树和右子树。
中序遍历先递归地遍历左子树,然后访问根节点,最后遍历右子树。
后序遍历先递归地遍历左子树和右子树,最后访问根节点。
树的遍历操作的时间复杂度为O(n),其中n是树的节点数。
综上所述,树的基本操作包括插入、删除、和遍历。
这些操作在解决各种实际问题和算法中起着重要的作用。
掌握了树的基本操作,可以更好地理解和应用数据结构和算法。
同时,对于日常编程工作和面试准备也是非常有帮助的。
树结构的定义和基本操作树结构是一种非线性的数据结构,其形状类似于自然界中的树。
树由一组节点(或称为顶点)和一组连接这些节点的边组成。
树结构的常见学习对象有二叉树、二叉树、AVL树、红黑树等。
树结构的基本操作包括创建、插入、删除、查找和遍历。
首先,创建树结构需要定义树节点的结构。
每个节点至少包含一个数据元素以及指向其子节点的指针。
树结构可以使用链式存储结构或数组存储结构。
1.创建树结构:树结构的创建有多种方式。
其中一种常见的方法是通过递归实现。
递归函数首先创建根节点,然后再递归地创建根节点的左子树和右子树。
2.插入节点:要插入一个新节点,首先要定位到合适的位置。
比较要插入的节点值与当前节点值的大小,如果小于当前节点,则进入左子树,如果大于当前节点,则进入右子树。
最终找到合适的位置插入新节点。
如果要插入的节点已经存在,可以替换或忽略该节点。
3.删除节点:删除节点分为三种情况:删除叶子节点、删除只有一个子节点的节点、删除有两个子节点的节点。
-删除叶子节点:直接删除即可。
-删除只有一个子节点的节点:将子节点与父节点连接起来,删除当前节点。
-删除有两个子节点的节点:找到当前节点的后继节点(比当前节点大的最小节点),将后继节点的值复制到当前节点,然后删除后继节点。
4.查找节点:树的查找可以使用递归或迭代的方式实现。
递归方式从根节点开始,根据节点值与目标值的大小关系递归地遍历左子树或右子树,直到找到目标值或遍历完成。
迭代方式使用循环和栈或队列的数据结构来实现。
5.遍历节点:树的遍历有三种方式:前序遍历、中序遍历和后序遍历。
-前序遍历:根节点->左子树->右子树-中序遍历:左子树->根节点->右子树-后序遍历:左子树->右子树->根节点树的遍历也可以通过递归或迭代的方式实现。
递归方式较为简单,使用迭代方式需要借助栈或队列来保存遍历的节点。
除了上述基本操作外,树结构还有一些扩展的操作,如树的深度计算、查找最大值或最小值、查找前驱节点或后继节点等。
c语⾔数据结构树的基本操作树的基本操作有创建,插⼊,删除,以及各种遍历的应⽤,如:利⽤后序遍历求⾼度,利⽤前序遍历求层数的结点基本算法思路:创建⼆叉树函数参数必须接受⼆级指针!如果使⽤同级指针,⽆法返回创建后的结果,利⽤递归malloc函数完成创建 插⼊(检索树):根据检索树特性,在插⼊必须判断根节点左右两边的值来完成插⼊ 删除:如果删除的是节点是叶结点,直接free。
如果有⼀个⼦树,将其⽗节点指向删除节点的⼉⼦。
如果两个⼦树,遍历右节点找到最⼤的data,将他的data复制给删除data,然后删除该节(重复第⼀⼆种情况)更多应⽤举例请看代码(普通⼆叉树,检索树)#include<stdio.h>#include<stdlib.h>#include<string.h>#include<iostream>#include<conio.h>struct tree1 {char data;//数据域struct tree1* light;//指向左孩⼦的指针struct tree1* right;//指向右孩⼦的指针};char ch;struct tree1* root;struct tree1 *del_node1= NULL;//需要删除的节点void create(struct tree1** p);//创造⽽叉树void create_tree();//创造检索树void front(struct tree1* p);//前序遍历void midder(struct tree1* p);//中序遍历void post(struct tree1* p);//后序遍历void toot(struct tree1* p);//以括号的形式输出⼆叉树//int h(struct tree1* p);//求该节点的⾼度struct tree1* enter_node(char a, struct tree1** p);//插⼊检索树的节点struct tree1* find_father(struct tree1* p);//返回⽗节点的指针,若⽆寻找不到则返回空指针,函数不接受根节点!struct tree* find_rmax(struct tree1* p);//寻找右节点中的最⼤值int find_layer(struct tree1* p,char a,int n);//寻找树中指定内容并返回层数int find_node(struct tree1* p, char a);//如果有结点返回1,没有返回0int layer = 0;//接收节点层数void main(){root = NULL;printf("输⼊#代表此节点为终端结点\n");create(&root);front(root);printf("\n");midder(root);printf("\n");post(root);printf("\n");toot(root);printf("\n");printf("%d\n", find_layer(root, 'H', 1));}void create(struct tree1** p){std::cin >> ch;if (ch == '#'){*p = NULL;return;}else{*p = (struct tree1*)malloc(sizeof(struct tree1));(*p)->data = ch;create(&((*p)->light));create(&((*p)->right));}}void front(struct tree1* p){if (p != NULL){printf("%c", p->data);front(p->light);front(p->right);}}void midder(struct tree1* p){if (p != NULL){midder(p->light);printf("%c", p->data);midder(p->right);}}void post(struct tree1* p){if (p != NULL){post(p->light);post(p->right);printf("%c", p->data);}}void toot(struct tree1* p){if (p == NULL){printf("0");return;}printf("%c", p->data);if (p->light == NULL && p->right == NULL){return;}printf("(");toot(p->light);printf(",");toot(p->right);printf(")");}void create_tree(){struct tree1* p=NULL;int hj = 0;char c;root = (struct tree1*)malloc(sizeof(struct tree1));//⾃⼰赋值根节点的数据域std::cin >> c;root->data = c;root->light = NULL;root->right = NULL;//以#结束创建while (1){std::cin >> c;if (c == '#')break;if (hj == 0){hj++;p=enter_node(c, &(root));}else{p= enter_node(c, &p);}}}struct tree1* enter_node(char a,struct tree1 **p){if (*p == NULL)return NULL;//插⼊if (((*p)->light) == NULL && ((*p)->right) == NULL){struct tree1* new1 = (struct tree1*)malloc(sizeof(struct tree1)); new1->light = new1->right = NULL;new1->data = a;if (strcmp(&a, &((*p)->data)) > 0){((*p)->right) = new1;}else{((*p)->light) = new1;return new1;}if (strcmp(&a, &(*p)->data) > 0){enter_node(a, &((*p)->right));}else{enter_node(a, &((*p)->light));}}void del_node(struct tree1* p){struct tree1* father;//临时的存储的⽗节点struct tree1** father1;//真正的⽗节点p = del_node1;if (p->light == NULL || p->right == NULL)//删除叶⼦结点free(p);if (p->light != NULL && p->right == NULL || p->right != NULL && p->light == NULL)//只有⼀个结点 {father = find_father(root);//接收该节点的⽗节点father1 = &father;//判断是⽗节点的哪个⽅向的⼉⼦if (father->light == p){if (p->light == NULL){(*father1)->light = p->right;}else{(*father1)->light = p->light;}}else{if (p->light == NULL){(*father1)->right = p->right;}else{(*father1)->right = p->light;}}}}struct tree1* find_father(struct tree1* p){if (p == NULL){return NULL;}if (p->light == del_node1 || p->right == del_node1){return p;}find_father(p->light);find_father(p->right);}int find_layer(struct tree1* p, char a, int n){int c,g;int b=0;//判断是否有该节点if (p == NULL){return0 ;}if(p->data==a){return n;}c=find_layer(p->light, a, n + 1);g=find_layer(p->right, a, n + 1);if (c >= g){return c;else{return g;}}int find_node(struct tree1* p, char a) {if (p->data == a){return1;}if (p = NULL){return0;}int c, g;c = find_node(p->light, a);g = find_node(p->right, a);if (c >= g){return c;}else{return g;}}。
数据结构实验三实验报告数据结构实验三实验报告一、实验目的本次实验的目的是通过实践掌握树的基本操作和应用。
具体来说,我们需要实现一个树的数据结构,并对其进行插入、删除、查找等操作,同时还需要实现树的遍历算法,包括先序、中序和后序遍历。
二、实验原理树是一种非线性的数据结构,由结点和边组成。
树的每个结点都可以有多个子结点,但是每个结点只有一个父结点,除了根结点外。
树的基本操作包括插入、删除和查找。
在本次实验中,我们采用二叉树作为实现树的数据结构。
二叉树是一种特殊的树,每个结点最多只有两个子结点。
根据二叉树的特点,我们可以使用递归的方式实现树的插入、删除和查找操作。
三、实验过程1. 实现树的数据结构首先,我们需要定义树的结点类,包括结点值、左子结点和右子结点。
然后,我们可以定义树的类,包括根结点和相应的操作方法,如插入、删除和查找。
2. 实现插入操作插入操作是将一个新的结点添加到树中的过程。
我们可以通过递归的方式实现插入操作。
具体来说,如果要插入的值小于当前结点的值,则将其插入到左子树中;如果要插入的值大于当前结点的值,则将其插入到右子树中。
如果当前结点为空,则将新的结点作为当前结点。
3. 实现删除操作删除操作是将指定的结点从树中移除的过程。
我们同样可以通过递归的方式实现删除操作。
具体来说,如果要删除的值小于当前结点的值,则在左子树中继续查找;如果要删除的值大于当前结点的值,则在右子树中继续查找。
如果要删除的值等于当前结点的值,则有三种情况:- 当前结点没有子结点:直接将当前结点置为空。
- 当前结点只有一个子结点:将当前结点的子结点替代当前结点。
- 当前结点有两个子结点:找到当前结点右子树中的最小值,将其替代当前结点,并在右子树中删除该最小值。
4. 实现查找操作查找操作是在树中寻找指定值的过程。
同样可以通过递归的方式实现查找操作。
具体来说,如果要查找的值小于当前结点的值,则在左子树中继续查找;如果要查找的值大于当前结点的值,则在右子树中继续查找。
浙江大学城市学院实验报告课程名称数据结构与算法实验项目名称实验五二叉搜索树的基本操作学生姓名蓝礼巍专业班级学号实验成绩指导老师(签名)日期一.实验目的和要求1.掌握二叉搜索树的基本概念。
2.掌握二叉搜索树基本操作的实现。
二. 实验内容1. 设在一棵二叉搜索树的每个结点的data域中,含有关键字key域和统计相同关键字元素个数的count域。
当向该树插入一个元素时,若树中已有相同关键字值的结点,则使该结点的count域值增1,否则由该元素值生成一个新结点插入到该树中,并使其count域值为1。
当向该树删除一个元素时,若树中该元素结点的count域值大于1,则使该结点的count域值减1,否则(count 域值等于1)删除该结点。
编写头文件bstree.h,实现上述二叉搜索树的存储结构定义与基本操作实现函数;编写主函数文件test8_1.cpp,验证头文件中各个操作。
基本操作包括:①void InitBSTree(BTreeNode *&bst);//初始化该二叉搜索树②void PrintBSTree(BTreeNode *bst);//以广义表形式输出该二叉搜索树(输出内容包括关键字值与相同元素个数值)③void Insert (BTreeNode *&bst, ElemType item);//插入一个元素到该二叉搜索树(用非递归算法实现)④int Delete (BTreeNode *&bst , ElemType item);//从二叉搜索树中删除某个元素(用非递归算法实现)⑤ElemType MaxBSTree(BTreeNode *bst);//求该二叉搜索树的最大关键字值(用非递归算法实现)2.选做:编写下列操作的实现函数,添加到头文件bstree.h中,并在主函数文件test8_1.cpp中添加相应语句进行测试。
①void PrintNode1(BTreeNode *bst);//按递减序打印二叉搜索树中所有左子树为空,右子树非空的结点数据域的值②void PrintNode2(BTreeNode *bst, int x );//从小到大输出二叉搜索树中所有关键字值>=x 的结点数据域的值3. 填写实验报告,实验报告文件取名为report5.doc。
树的基本操作。
树是一种非常常见的数据结构,它由节点和边组成。
树的基本操作包括插入节点、删除节点、查找节点、遍历以及求树的深度等。
插入节点是树的基本操作之一。
插入节点的过程是将一个新节点添加到树中的合适位置。
具体步骤是从根节点开始,比较新节点的值与当前节点的值的大小关系,根据比较结果选择向左子树或者右子树继续比较,直到找到合适的位置插入新节点。
删除节点也是树的基本操作之一。
删除节点的过程是先找到待删除的节点,然后根据节点的子节点情况进行删除。
如果待删除的节点没有子节点,直接删除即可;如果待删除的节点只有一个子节点,将子节点取代待删除的节点即可;如果待删除的节点有两个子节点,可以选择使用左子树的最大值或者右子树的最小值来取代待删除的节点,并删除对应的最大或最小节点。
查找节点也是树的基本操作之一。
查找节点的过程是从根节点开始,比较目标值与当前节点的值的大小关系,根据比较结果选择向左子树或者右子树继续比较,直到找到目标值对应的节点或者遍历到叶子节点仍未找到。
树的遍历也是树的基本操作之一。
树的遍历分为深度优先遍历和广度优先遍历两种方式。
深度优先遍历包括前序遍历、中序遍历和后序遍历。
前序遍历是先访问当前节点,然后递归访问左子树和右子树;中序遍历是先递归访问左子树,然后访问当前节点,最后递归访问右子树;后序遍历是先递归访问左子树和右子树,最后访问当前节点。
广度优先遍历是按层次依次访问每个节点,通常使用队列来实现。
求树的深度也是树的基本操作之一。
求树的深度的过程是从根节点开始,递归计算左子树和右子树的深度,取较大值加1即为树的深度。
树的基本操作包括插入节点、删除节点、查找节点、遍历以及求树的深度等。
这些基本操作在实际应用中非常重要,可以用来解决各种问题,例如构建搜索树、实现文件系统等。
掌握树的基本操作对于理解和应用其他高级数据结构也非常有帮助。
因此,学习和掌握树的基本操作是很有必要的。
数据结构实验报告报告名称树的操作专业网络工程班级1001学号29姓名张剑指导教师陈淑红李珍辉黄哲2012年5月22日一、实验目的:熟练掌握树的基本操作,进一步理解树的非线性特点,递归性特点和动态数据结构特点二、实验内容与基本要求:1. 建立二叉树的二叉链表,2. 统计二叉树中叶子结点个数3. 求二叉树深度三、概要设计:1.数据结构:ADT Tree{数据对象D:D是具有相同特性的数据元素的集合。
数据关系R:若D为空集,则称为空树。
2.抽象数据类型:基本操作P:Inittree(&T);操作结果:构造空树T。
DestoryTree(*T)初始条件:树T存在。
操作结果:销树T。
CreateTree(&T)初始条件:definition给树T的定义。
操作结果;按definition构造树T。
ClearTree(&T)初始条件:树T存在。
操作结果:将树T清为空树。
TreeEmpty(T)初始条件:树T存在。
操作结果:若T为空树,则返回TURE,否则返回FALSE。
TreeDepth(T)初始条件:树T存在。
操作结果:返回T的深度。
Root(T)初始条件:树T存在。
操作结果:返回T的根。
Valul(T,cur-e)初始条件:树T存在,cur-e是T中某个结点。
操作结果:返回cur-e的值。
Assign(T,cur-e,value);初始条件:树T存在,cur-e是T中某个结点。
操作结果:结点cur-e赋值为alue。
Parent(T,cur-e)初始条件:树T存在,cur-e是T中某个结点。
操作结果:若cur-e是T的非根结点,怎返回它的双亲,否则函数值为空。
LeftChild(T,cur-e);初始条件:树T存在,cur-e是T中某个结点。
操作结果:若cur-e是T的非叶子结点,则返回它的左孩子,否则返回空。
RightSibling(T,cur-e);初始条件:树T存在,cur-e是T中某个结点。
实验名称:树的操作实验实验目的: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. 堆排序:利用二叉堆的属性,实现高效排序。
实验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.顺序存储七、思考讨论题或体会或对改进实验的建议通过这次实验,我掌握了二叉树的顺序存储和链式存储,体会了二叉树的存储结构的特性,掌握了二叉树的树上相关操作。
数据结构树结构的基本操作树结构是一种用于组织和存储数据的非线性数据结构。
它由节点和边组成,节点之间以层次关系相连,每个节点可以有多个子节点。
在树结构中,存在一些基本的操作,包括树的创建、插入节点、删除节点、查找节点等。
本文将详细介绍树结构的基本操作,并提供相应的示例和代码。
一、树的创建树的创建是指在空树中添加节点,形成一棵具有层次关系的树。
常见的创建方式有手动创建和从已有的数据中创建两种。
手动创建树的过程如下:首先,创建一个根节点,并给它赋予一个值;然后,给根节点添加子节点,每个子节点都有一个父节点,组成层次结构;逐步添加子节点,形成完整的树。
例如,创建一个有5个节点的二叉树,代码如下:```pythonclass TreeNode:def __init__(self, value):self.left = Noneself.right = Noneself.val = value# 手动创建二叉树root = TreeNode('A')root.left = TreeNode('B')root.right = TreeNode('C')root.left.left = TreeNode('D')root.left.right = TreeNode('E')```二、插入节点插入节点是指在树中添加新的节点。
插入节点的位置可以根据某种规则确定,常用的插入方式有在树的最后插入、插入为左子节点和插入为右子节点等。
例如,在上述创建的二叉树中插入节点'F'作为节点'E'的左子节点,代码如下:```python# 在节点'E'的左侧插入新的节点'F'new_node = TreeNode('F')root.left.right.left = new_node```三、删除节点删除节点是指在树中删除指定的节点。
南邮数据结构实验报告实验目的,通过本次实验,我们旨在加深对数据结构的理解,掌握数据结构的基本操作和算法设计能力,提高对数据结构的应用能力和实际问题的解决能力。
一、实验内容。
1. 实验一,线性表的基本操作。
本次实验中,我们首先学习了线性表的基本概念和操作,包括插入、删除、查找等操作,并通过实际编程操作来加深对线性表的理解。
2. 实验二,栈和队列的应用。
在实验二中,我们通过实际编程操作来学习栈和队列的应用,包括中缀表达式转换为后缀表达式、栈的应用、队列的应用等内容。
3. 实验三,树和二叉树的基本操作。
实验三中,我们学习了树和二叉树的基本概念和操作,包括树的遍历、二叉树的建立和遍历等内容,并通过实际编程操作来加深对树和二叉树的理解。
4. 实验四,图的基本操作。
最后,我们学习了图的基本概念和操作,包括图的存储结构、图的遍历等内容,并通过实际编程操作来加深对图的理解。
二、实验过程。
在实验过程中,我们首先对实验内容进行了深入的学习和理解,掌握了数据结构的基本概念和操作方法。
然后,我们通过实际编程操作来加深对数据结构的理解,并通过调试和修改程序来提高对数据结构的应用能力和实际问题的解决能力。
在实验过程中,我们遇到了一些问题,但通过不懈的努力和团队合作,最终顺利完成了实验任务。
三、实验结果与分析。
通过本次实验,我们深入理解了数据结构的基本概念和操作方法,掌握了线性表、栈、队列、树、二叉树和图的基本操作,并通过实际编程操作加深了对数据结构的理解。
同时,我们也提高了对数据结构的应用能力和实际问题的解决能力,为今后的学习和工作打下了坚实的基础。
四、实验总结。
通过本次实验,我们不仅加深了对数据结构的理解,还提高了对数据结构的应用能力和实际问题的解决能力。
在今后的学习和工作中,我们将继续努力,不断提升自己的专业能力,为将来的发展打下坚实的基础。
以上就是本次实验的报告内容,谢谢!。
实验五二叉树基本操作的编程实现【实验目的】内容:二叉树基本操作的编程实现要求:二叉树基本操作的编程实现(2学时,验证型),掌握二叉树的建立、遍历、插入、删除等基本操作的编程实现,也可以进一步编程实现查找等操作,存储结构主要采用顺序或链接结构。
也鼓励学生利用基本操作进行一些应用的程序设计。
【实验性质】验证性实验(学时数:2H)【实验内容】以下的选题都可以作为本次实验的推荐题目1.建立二叉树,并以前序遍历的方式将结点内容输出。
2.将一个表示二叉树的数组结构转换成链表结构。
3.将表达式二叉树方式存入数组,以递归方式建立表达式之二叉树状结构,再分别输出前序、中序及后序遍历结果,并计算出表达式之结果。
【思考问题】1.二叉树是树吗?它的定义为什么是递归的?2.三种根序遍历主要思路是什么?3.如果不用遍历算法一般启用什么数据结构实现后序遍历?4.举出二叉树的应用范例?【参考代码】(一)建立二叉树,并以前序遍历的方式将结点内容输出*//*===============================================*//*程序构思:*//*输入元素值后建立二叉树,以递归的方式做前序遍历,*//*其顺序为:结点-左子-右子树,并将二叉树结点内容输出。
*/#include<stdlib.h>#include<stdio.h>struct tree /*声明树的结构*/{struct tree *left; /*存放左子树的指针*/int data; /*存放结点数据内容*/struct tree *right; /*存放右子树的指针*/};typedef struct tree treenode; /*声明新类型树结构*/typedef treenode *b_tree; /*声明二叉树的链表*//*===============================================*//*插入二叉树结点*//*===============================================*/b_tree insert_node (b_tree root, int node){b_tree newnode; /*声明树根指针*/b_tree currentnode; /*声明目前结点指针*/b_tree parentnode; /*声明父结点指针*//*建立新结点的内存空间*/newnode=(b_tree )malloc (sizeof(treenode));newnode->data=node; /*存入结点内容*/ newnode->right=NULL; /*设置右指针初值*/ newnode->left=NULL; /*设置左指针初值*/if (root==NULL)return newnode; /*返回新结点的位置*/ else{currentnode=root; /*存储目前结点指针*/while (currentnode!=NULL){parentnode=currentnode; /*存储父结点指针*/if (currentnode->data>node) /*比较结点的数值大小*/currentnode=currentnode->left; /*左子树*/elsecurrentnode=currentnode->right; /*右子树*/ }if (parentnode->data>node) /*将父结点和子结点做连结*/ parentnode->left=newnode; /*子结点为父结点之左子树*/ elseparentnode->right=newnode; /*子结点为父结点之右子树*/ }return root; /*返回根结点之指针*/ }/*===============================================*//*建立二叉树*//*===============================================*/b_tree create_btree (int *data, int len){b_tree root=NULL; /*根结点指针*/ int i;for (i=0; i<len; i++) /*建立树状结构*/ root=insert_node(root, );return root;}/*===============================================*//*二叉树前序遍历*//*===============================================*/void preorder (b_tree point){if (point!=NULL) /*遍历的终止条件*/ {printf ("%2d", point->data); /*处理打印结点内容*/preorder (point->left); /*处理左子树*//*处理右子树*/}}/*==================================================*//*主程序:建立二叉树,并以前序遍历输出二叉树结点内容*//*==================================================*/void main(){b_tree root=NULL; /*树根指针*/int i, index;int value; /*读入输入值所使用的暂存变量*/ int nodelist[20]; /*声明存储输入数据之数组*/printf ("\n Please input the elements of binary tree(Exit for 0): \n");index=0;/*------------------读取数值存到数组中------------------*/scanf ("%d", &value); /*读取输入值存到变量value*/while (value!=0){nodelist[index]=value;;scanf ("%d", &value);}/*----------------------建立二叉树----------------------*/root=create_btree(nodelist, index);/*--------------------前序遍历二叉树--------------------*/printf ("\n The preorder traversal result is (");preorder( );printf (") \n");}/*希望的结果*/ /*Please input the elements of binary tree(Exit for 0): *//*6 3 1 9 5 7 4 8 0 *//* */ /*The preorder traversal result is (6 3 1 5 4 9 7 8) */(二)将一个表示二叉树的数组结构转换成链表结构/*===============================================*//*程序构思:*//*给定一个二叉树数组结构,使用递归方式建立一棵二叉树,*//*并中序遍历的方式输出二叉树结点内容。
北京邮电大学软件学院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. 删除树的操作能够依次删除树的每个节点,并及时释放内存。
六、实验结论通过本实验,我们掌握了树的基本操作,并应用树的特点解决了实际问题。
树作为一种非线性数据结构,具有广泛的应用价值,在算法和数据处理中发挥着重要作用。
七、实验感想通过本次实验,我们深入理解了树的结构和操作,并学会了如何应用树来解决实际问题。
树的递归结构使得其遍历和搜索操作非常高效,能够快速地定位和处理数据。
同时,树的删除操作也需要特别小心,避免出现内存泄漏等问题。
目录实验一线性表基本操作的编程实现 (201)实验二堆栈或队列基本操作的编程实现 (49)实验四二维数组基本操作的编程实现 (18)实验五二叉树基操作的编程实现 (20)实验六图基本操作的编程实现 (45)(特别提示:程序设计包含两个方面的错误。
其一是错误,其二是能错误。
为了提高学生的编程和能力,本指导书给出的程序代码并的两种错误。
并且也不保证程序的完整性,有一些语句已经故意删除,就是要求学生自己编制完成,这样才能达到我们的要求。
希望大家以自己所学高级语言的基本功和点为基础,不要过于依赖给出的参考代码,这样才能有所进步。
如果学生能够根据要求完全自己编制,那就不好了。
)实验一线性表基本操作的编程实现【实验目的】线性表基本操作的编程实现要求:线性表基本操作的编程实现(2学时,验证型),掌握线性表的建立、遍历、插入、删除等基本操作的编程实现,也可以进一步编程实现查找、逆序、排序等操作,存储结构可以在顺序结构或链表结分主要功能,也可以用菜单进行管理完成大部分功能。
还鼓励学生利用基本操作进行一些更实际的应用型程序设计。
【实验性质】【实验内容】把线性表的顺序存储和链表存储的数据插入、删除运算其中某项进行程序实现。
建议实现键盘输入数据以实现程序的通据的函数。
【注意事项】【思考问题】1.线性表的顺序存储和链表存储的差异?优缺点分析?2.那些操作引发了数据的移动?3.算法的时间效率是如何体现的?4.链表的指针是如何后移的?如何加强程序的健壮性?【参考代码】(一)利用顺序表完成一个班级学生课程成绩的简单管理1、预定义以及顺序表结构类型的定义(1)#define ListSize //根据需要自己设定一个班级能够容纳的最大学生数(2)typedef struct Stu{int num; //学生的学号char name[10]; //学生的姓名float wuli; //物理成绩float shuxue; //数学成绩float yingyu; //英语成绩}STUDENT; //存放单个学生信息的结构体类型typedef struct List{stu[ListSize]; //存放学生的数组定义,静态分配空间int length; //记录班级实际学生个数}LIST; //存放班级学生信息的顺序表类型2、建立班级的学生信息void listcreate(LIST *Li,int m) //m为该班级的实际人数{int i;Li->length=0;for(i=0;i<m;i++) //输入m个学生的所有信息{printf("please input the %dth student's information:\n",i+1);printf("num=");scanf("%d", ); //输入第i个学生的学号printf("name=");scanf("%s", ); //输入第i个学生的姓名printf("wuli=");scanf("%f", ); //输入第i个学生的物理成绩printf("shuxue=");scanf("%f", ); //输入第i个学生的数学成绩printf("yingyu=");scanf("%f", ); //输入第i个学生的英语成绩Li->length++; //学生人数加1}}3、插入一个学生信息int listinsert(LIST *Li,int i) //将学生插入到班级Li的第i个位置。
实验四一、实验目的及要求掌握树的动态存储结构--二叉链表,掌握树的两种遍历方法,会运用两种遍历的方法求解有关问题。
二、实验环境硬件:计算机 软件:Microsoft Visual C++ 三、实验内容1. 以二叉链表作存储结构,建立一棵树;2. 输出其先根、后根遍历序列;3. 统计其叶子结点数;4. 求出它的深度。
四、调试过程及实验结果五、总结总的感觉就是树和二叉树的操作基本一致,基本都是依赖于二叉树才建立存储结构的,所以,对于树的操作,关键还是在于对二叉树操作的掌握。
本次程序的编写靠的是我对二叉树的熟悉运用,还有相关树的知识的掌握,再借助百度上的一些别人的程序,本人终于写出了自己的程序,甚是欣慰!课程名称:数据结构班级:一班 完成日期:11,27 姓名:王辉东学号:1010431129 指导教师:王群芳 实验名称:树的应用实验序号: 实验成绩:六、附录(源程序清单)#include<stdio.h>#include<stdlib.h>typedef struct CSNode{char data;struct CSNode *firstchild, *nextsibling;}CSNode, *CSTree;void createtree(CSTree &T)//以二叉树创建树{char ch;ch=getchar();if(ch==' ') T=NULL;else{if(!(T=(CSNode *)malloc(sizeof(CSNode)))) printf("分配空间出错!"); T->data=ch;createtree(T->firstchild);createtree(T->nextsibling);}}void visit(CSTree T)//遍历函数,输出结点{if(T)printf("%c",T->data);elseprintf("树不存在,输出错误!");}void preroot(CSTree T)//先根输出{if(T){visit(T);preroot(T->firstchild);preroot(T->nextsibling);}}void postroot(CSTree T)//后根输出相当于二叉树中序遍历{if(T){postroot(T->firstchild);visit(T);postroot(T->nextsibling);}int n=0;int countleaf(CSTree T){if(T!=NULL){countleaf(T->firstchild);if(T->firstchild==NULL) n++;countleaf(T->nextsibling);}return n;}int depth(CSTree T){int firstdepth,nextdepth;if(!T) return 0;else{firstdepth=depth(T->firstchild);nextdepth=depth(T->nextsibling);}return firstdepth+1>nextdepth?firstdepth+1:nextdepth;}int main(){CSTree T;printf("请输入树的结点,以二叉树的格式创建,空格表示无左右孩子:\n"); createtree(T);printf("\n先根输出树的结点:\n");preroot(T);printf("\n后根输出树的结点:\n");postroot(T);printf("\n树的深度是depth=%d",depth(T));printf("\n树的叶子数目是leaf=%d\n",countleaf(T));while(1);return 0;}。
数据结构-树的基本操作#include <stdio.h>#include <malloc.h>#include "GTree.h"#include "LinkList.h"typedef struct _tag_GTreeNode GTreeNode; /* 树的节点 */struct _tag_GTreeNode{GTreeData* data; /* 节点⾃⾝数据 */GTreeNode* parent; /* ⽗亲节点 */LinkList* child; /* 孩⼦链表 */};typedef struct _tag_TLNode TLNode; /* 链表节点结构体,将树节点串成链表 */struct _tag_TLNode{LinkListNode header;GTreeNode* node;};static void recursive_display(GTreeNode* node, GTree_Printf* pFunc, int format, int gap, char div)/* 递归打印函数定义为static外界看不到 format--缩进单位个数 gap--缩进单位 div--缩进形式 pFunc--打印函数*/ {int i = 0;if( (node != NULL) && (pFunc != NULL) ){for(i=0; i<format; i++){printf("%c", div);}pFunc(node->data); /* 打印数据 */printf("\n");for(i=0; i<LinkList_Length(node->child); i++){TLNode* trNode = (TLNode*)LinkList_Get(node->child, i);recursive_display(trNode->node, pFunc, format + gap, gap, div);}}}static void recursive_delete(LinkList* list, GTreeNode* node) /* 递归删除函数要删除该节点的所有函数 */{if( (list != NULL) && (node != NULL) ){GTreeNode* parent = node->parent; /* 要删除的节点的⽗亲节点 */int index = -1;int i = 0;for(i=0; i<LinkList_Length(list); i++) /* 从树的组织链表中删除该节点 */{TLNode* trNode = (TLNode*)LinkList_Get(list, i);if( trNode->node == node ){LinkList_Delete(list, i);free(trNode);index = i; /* 标记位:表⾯从组织链表中删除成功 */break;}}if( index >= 0 ){if( parent != NULL ) /* 从⽗亲节点的孩⼦链表中删除该节点 */{for(i=0; i<LinkList_Length(parent->child); i++){TLNode* trNode = (TLNode*)LinkList_Get(parent->child, i);if( trNode->node == node ){LinkList_Delete(parent->child, i);free(trNode);break;}}}while( LinkList_Length(node->child) > 0 ) /* 删除要删除的节点的孩⼦节点 */{TLNode* trNode = (TLNode*)LinkList_Get(node->child, 0); /* 从孩⼦链表中⼀个⼀个取出来递归删除所有孩⼦节点 */recursive_delete(list, trNode->node);}LinkList_Destroy(node->child); /* 销毁要删除节点的孩⼦链表 */free(node); /* 将insert申请的内存释放 */}}}static int recursive_height(GTreeNode* node) /* 递归算出树的⾼度计算⼀个树的⾼度⾸先要算出⼦树的⾼度后+1 */{int ret = 0;if( node != NULL ){int subHeight = 0;int i = 0;for(i=0; i<LinkList_Length(node->child); i++){TLNode* trNode = (TLNode*)LinkList_Get(node->child, i); /* 从链表中取出⼦树的根节点 */subHeight = recursive_height(trNode->node);if( ret < subHeight ){ret = subHeight;}}ret = ret + 1; /* 加上根节点故要+1 */}return ret;}static int recursive_degree(GTreeNode* node) /* 定义静态函数外部⽆法看到递归算出 */{int ret = -1;if( node != NULL ){int subDegree = 0;int i = 0;ret = LinkList_Length(node->child);for(i=0; i<LinkList_Length(node->child); i++){TLNode* trNode = (TLNode*)LinkList_Get(node->child, i);subDegree = recursive_degree(trNode->node);if( ret < subDegree ) /* 取最⼤值 */{ret = subDegree;}}}return ret;}GTree* GTree_Create(){return LinkList_Create();}void GTree_Destroy(GTree* tree) /* 此处数据封装⽤户表⾯看起来只是⼀个tree(实际为⼀个单链表) */{GTree_Clear(tree);LinkList_Destroy(tree);}void GTree_Clear(GTree* tree){GTree_Delete(tree, 0); /* 删除根节点就相当于删除整个树 */}int GTree_Insert(GTree* tree, GTreeData* data, int pPos) /* pPos---代表要插⼊的数据的⽗亲在表中的位置 */{LinkList* list = (LinkList*)tree;int ret = (list != NULL) && (data != NULL) && (pPos < LinkList_Length(list)); /* 合法性检测 pPos⾄少⼩于树节点(链表)长度 */if( ret ){TLNode* trNode = (TLNode*)malloc(sizeof(TLNode)); /* (树)组织节点 */TLNode* cldNode = (TLNode*)malloc(sizeof(TLNode)); /* child节点 *---插⼊某个节点时,要将其插⼊两个链表,⼀个是组织链表,⼀个是⽗亲节点的⼦节点链表 */ TLNode* pNode = (TLNode*)LinkList_Get(list, pPos); /* 从树中(链表)中取出pPos位置的节点强制转换为TLnode---⾥⾯有指向树节点的指针 */GTreeNode* cNode = (GTreeNode*)malloc(sizeof(GTreeNode)); /* 申请⼀个树节点 */ret = (trNode != NULL) && (cldNode != NULL) && (cNode != NULL);if( ret ){cNode->data = data; /* 对新创建的通⽤节点赋值 */cNode->parent = NULL; /* 暂时指定该节点没有双亲 */cNode->child = LinkList_Create();trNode->node = cNode;cldNode->node = cNode;LinkList_Insert(list, (LinkListNode*)trNode, LinkList_Length(list)); /* 插⼊到组织链表中 */if( pNode != NULL ) /* 根节点没有双亲故此处要判断 */{cNode->parent = pNode->node; /* 将申请的节点赋给⽗亲节点 */LinkList_Insert(pNode->node->child, (LinkListNode*)cldNode, LinkList_Length(pNode->node->child)); /* 插⼊到⽗亲节点的孩⼦链表中 */ }}else{free(trNode);free(cldNode);free(cNode);}}return ret;}GTreeData* GTree_Delete(GTree* tree, int pos){TLNode* trNode = (TLNode*)LinkList_Get(tree, pos);GTreeData* ret = NULL; /* 要删除的节点⾥保存的数据 */if( trNode != NULL ){ret = trNode->node->data;recursive_delete(tree, trNode->node); /* 递归删除,要删除所有孩⼦ */}return ret;}GTreeData* GTree_Get(GTree* tree, int pos) /* 从组织链表中pos节点的数据返回 */{TLNode* trNode = (TLNode*)LinkList_Get(tree, pos);GTreeData* ret = NULL;if( trNode != NULL ){ret = trNode->node->data;}return ret;}GTreeData* GTree_Root(GTree* tree){return GTree_Get(tree, 0);}int GTree_Height(GTree* tree){TLNode* trNode = (TLNode*)LinkList_Get(tree, 0);int ret = 0;if( trNode != NULL ){ret = recursive_height(trNode->node);}return ret;}int GTree_Count(GTree* tree){return LinkList_Length(tree);}int GTree_Degree(GTree* tree){TLNode* trNode = (TLNode*)LinkList_Get(tree, 0);int ret = -1;if( trNode != NULL ){ret = recursive_degree(trNode->node);}return ret;}void GTree_Display(GTree* tree, GTree_Printf* pFunc, int gap, char div){TLNode* trNode = (TLNode*)LinkList_Get(tree, 0);if( (trNode != NULL) && (pFunc != NULL) ){recursive_display(trNode->node, pFunc, 0, gap, div);}}。
线性结构中的一个结点至多只有一个直接后继,而树形结构的特点是一个结点可以有多个直接后继(包括一个),因此,树形结构可以表达更复杂的数据。
现实世界中的很多事物可以用树形结构来描述。
例如,人类社会中家族成员之间的血统关系可以很自然的表示成一个树形结构。
树的概念树(Tree)是一类重要的树形结构,其定义如下:树是n (n≥0)个结点的有限集合,一棵树满足以下两个条件:①当n=0时,称为空树;②当n>0时,有且仅有一个称为根的结点,除根结点以外,其余结点分为m(m≥0)个互不相交的非空集合T1,T2…Tm,这些集合中的每一个都是一棵树,称为根的子树。
树的基本运算包括:①求根Root(bt),求树T的根结点。
②求双亲Parent(T,X),求结点X在树T上的双亲;若X是树T的根或X不在T上,则结果为一特殊标志。
③求孩子Child(T,X,i),求树T上结点X的第i个孩子结点,若X 不在T上或X没有第i个孩子,则结果为一特殊标志。
④建树Create(X,T1…,Tk),k>1,是建立一棵树以X为根,以T1,…Tk为第1,…k棵子树的树。
⑤剪技Delete(T,X,i),删除树T上结点X的第i棵子树;若T无第i棵子树,则这空操作。
⑥遍历(TraverseTree(bt):遍历树,即访问树中的每个结点,且每个结点仅被访问一次。
二叉树二叉树的基本概念二叉树(Binary Tree)是n(n≥0)个元素的有限集合,该集合或者为空,或由一个根及两棵互不相交的左子树和右子树组成。
其中左右子树也是二叉树。
它或者是空集,或者同时满足下述两个条件。
一般地,二叉树可以有五种基本形态。
如图所示。
由此可见,二叉树的形态比较规整,这决定了二叉树的操作及存储比较简便。
二叉树的基本运算包括:①初始化Initiate(BTREE),,其作用是设置一棵空二叉树BTREE=¢。
②求双亲Parent(BTREE,X),求结点X在二叉树BTREE上的双亲,若X是BTREE的根或X根本不是BTREE上的结点,运算结果为一特殊标志。
实验六二叉树的基本操作
一、实验目的
1.掌握二叉树的基本概念;
2.掌握二叉树的二叉链表的存储结构;
3.掌握利用括号法表示二叉树的的构建方法,以及先、中、后序遍历和层序遍历的实现。
二、实验相关知识
1.复习C语言文件读写的相关知识
2.复习课本中第6章关于数的相关知识点;
三、实验内容与要求
1.建立一棵用二叉链表方式存储的二叉树,并利用凹凸法进行二叉树的打印;并对其进行遍历(先序、中序、后序和层序),并打印输出遍历结果。
【设计要求】输入为括号法表示的二叉树字符串序列,补充完整以下函数,实现二叉链表的建立,二叉树的遍历、以及二叉树的竖向打印。
void CreateBiTree(BiTree *bt)
/*扩展的先序遍历结果构造二叉链表*/
void PreOrder(BiTree root)/*先序遍历二叉树*/
void PostOrder(BiTree root) /* 后序遍历二叉树*/
void InOrder(BiTree root) /* 中序遍历二叉树的非递归算法 */
int LayerOrder(BiTree bt) /* 层序遍历二叉树 */
void PrintTree(BiTree bt,int nLayer) /* 按竖向树状打印的二叉树 */
【测试用例】设有以下的二叉树:
则添加空孩子进行扩展之后:
1、输入:A(B(C,D(E,F(G))))
2、输出:
先序遍历:ABCDEFG
中序遍历:CBEDGFA
后序遍历:CEGFDBA
层序遍历:ABCDEFG
打印二叉树:
A
F
G
D
E
B
C
四、程序代码及运行结果
【程序代码】
#include<stdio.h>
#include<malloc.h>
#include<conio.h>
typedef char DataType;
//二叉链表的结点结构定义
typedef struct Node
{
DataType data;
struct Node *LChild;
struct Node *RChild;
}BiTNode, *BiTree;
typedef BiTree StackElementType;
typedef BiTree QueueElementType;
#include"stack.h"
#include"queue.h"
//构造二叉链表
void CreateBiTree(BiTNode *&bt, char *str1) {
BiTNode *St[Stack_Size], *p = NULL;
int top = -1, k = 0, j = 0;
char ch;
bt = NULL;
ch = str1[j];
while (ch != '\0')
{
switch (ch)
{
case'(':top++;
St[top] = p;
k = 1;
break;
case')':top--;
break;
case',':k = 2;
break;
default:p = (BiTNode *)malloc(sizeof(BiTNode));
p->data = ch;
p->LChild = p->RChild = NULL;
if (bt == NULL)
bt = p;
else
{
switch (k)
{
case 1:St[top]->LChild = p; break;
case 2:St[top]->RChild = p; break;
}
}
}
j++;
ch = str1[j];
}
}
void Visit(BiTree root)
{
if (root != NULL)
printf("%c ", root->data);
}
/*先序遍历二叉树, root为指向二叉树根结点的指针*/
void PreOrder(BiTree root)
{
if (root != NULL)
{
printf("%c ", root->data);
PreOrder(root->LChild);
PreOrder(root->RChild);
}
}
/* 后序遍历二叉树,root为指向二叉树(或某一子树)根结点的指针*/ void PostOrder(BiTree root)
{
if (root != NULL)
{
PostOrder(root->LChild);
PostOrder(root->RChild);
printf("%c ", root->data);
}
}
void InOrder(BiTree root) /* 中序遍历二叉树的非递归算法 */
{
if (root != NULL)
{
InOrder(root->LChild);
printf("%c ", root->data);
InOrder(root->RChild);
}
}
void PrintTree(BiTree bt, int nLayer) /* 按竖向树状打印的二叉树 */ {
if (bt == NULL)
return;
PrintTree(bt->RChild, nLayer + 3);
for (int i = 0; i < nLayer; i++)
printf(" ");
printf("%c\n", bt->data);
PrintTree(bt->LChild, nLayer + 3);
}
void LayerOrder(BiTree bt) /* 层序遍历二叉树 */
{
BiTree p;
BiTree qu[Stack_Size];
int front, rear;
front = rear = -1;
rear++;
qu[rear] = bt;
while (front != rear)
{
front = (front + 1) % Stack_Size;
p = qu[front];
printf("%c ", p->data);
if (p->LChild != NULL)
{
rear = (rear + 1) % Stack_Size;
qu[rear] = p->LChild;
}
if (p->RChild != NULL)
{
rear = (rear + 1) % Stack_Size;
qu[rear] = p->RChild;
}
}
}/* LayerOrder */
int main()
{
BiTNode *T;
//char str1[] = " "; //请输入括号法表示的二叉树序列char str1[Stack_Size];
printf("请输入括号法表示的二叉树序列:");
gets_s(str1);
printf("括号法表示的二叉树序列为%s:\n", str1);
CreateBiTree(T, str1);
printf("先序遍历输出序列为:");
PreOrder(T);
printf("\n中序遍历输出序列为:");
InOrder(T);
printf("\n后序遍历输出序列为:");
PostOrder(T);
printf("\n层序遍历输出序列为:");
LayerOrder(T);
printf("\n竖向打印二叉树:\n");
PrintTree(T, 1);
_getch();
return 0;
}
【运行结果】
巩固了二叉树的知识。