二叉树结点染色问题 实验报告
- 格式:doc
- 大小:149.50 KB
- 文档页数:10
实验报告:二叉树第一篇:实验报告:二叉树实验报告二叉树一实验目的1、进一步掌握指针变量,动态变量的含义;2、掌握二叉树的结构特性以及各种存储结构的特点及适用范围。
3、掌握用指针类型描述、访问和处理二叉树的运算。
4、熟悉各种存储结构的特征以及如何应用树结构解决具体问题。
二实验原理树形结构是一种应用十分广泛和重要的非线性数据结构,是一种以分支关系定义的层次结构。
在这种结构中,每个数据元素至多只有一个前驱,但可以有多个后继;数据元素之间的关系是一对多的层次关系。
树形结构主要用于描述客观世界中具有层次结构的数据关系,它在客观世界中大量存在。
遍历二叉树的实质是将非线性结构转为线性结构。
三使用仪器,材料计算机 2 Wndows xp 3 VC6.0四实验步骤【问题描述】建立一个二叉树,请分别按前序,中序和后序遍历该二叉树。
【基本要求】从键盘接受输入(按前序顺序),以二叉链表作为存储结构,建立二叉树(以前序来建立),并采用递归算法对其进行前序,中序和后序遍历,将结果输出。
【实现提示】按前序次序输入二叉树中结点的值(一个整数),0表示空树,叶子结点的特征是其左右孩子指针为空。
五实验过程原始记录基本数据结构描述; 2 函数间的调用关系;用类C语言描述各个子函数的算法;附录:源程序。
六试验结果分析将实验结果分析、实验中遇到的问题和解决问题的方法以及关于本实验项目的心得体会,写在实验报告上。
第二篇:数据结构-二叉树的遍历实验报告实验报告课程名:数据结构(C语言版)实验名:二叉树的遍历姓名:班级:学号:时间:2014.11.03一实验目的与要求1.掌握二叉树的存储方法2.掌握二叉树的三种遍历方法3.实现二叉树的三种遍历方法中的一种二实验内容• 接受用户输入一株二叉树• 输出这株二叉树的前根, 中根, 后根遍历中任意一种的顺序三实验结果与分析//*********************************************************** //头文件#include #include //*********************************************************** //宏定义#define OK 1 #define ERROR 0 #define OVERFLOW 0//*********************************************************** typedef struct BiTNode { //二叉树二叉链表存储结构char data;struct BiTNode *lChild,*rChild;}BiTNode,*BiTree;//******************************** *************************** int CreateBiTree(BiTree &T){ //按先序次序输入二叉中树结点的值,空格表示空树//构造二叉链表表示的二叉树T char ch;fflush(stdin);scanf(“%c”,&ch);if(ch==' ')T=NULL;else{ if(!(T=(BiTNode *)malloc(sizeof(BiTNode))))return(OVERFLOW);T->data=ch;Creat eBiTree(T->lChild);CreateBiTree(T->rChild);} return(OK);} //********************************************************* void PreOrderTraverse(BiTree T){ //采用二叉链表存储结构,先序遍历二叉树的递归算法if(T){ printf(“%c”,T->data);PreOrderTraverse(T->lChild);PreOrd erTraverse(T->rChild);} } /***********************************************************/ void InOrderTraverse(BiTree T){ //采用二叉链表存储结构,中序遍历二叉树的递归算法if(T){ InOrderTraverse(T->lChild);printf(“%c”,T->data);InOrderT raverse(T->rChild);} }//*********************************************************** void PostOrderTraverse(BiTree T){ //采用二叉链表存储结构,后序遍历二叉树的递归算法if(T){ PostOrderTraverse(T->lChild);PostOrderTraverse(T->rChild) ;printf(“%c”,T->data);} }//*********************************************************** void main(){ //主函数分别实现建立并输出先、中、后序遍历二叉树printf(“please input your tree follow the PreOrder:n”);BiTNode *Tree;CreateBiTree(Tree);printf(“n先序遍历二叉树:”);PreOrderTraverse(Tree);printf(“n中序遍历二叉树:”);InOrderTraverse(Tree);printf(“n后序遍历二叉树:”);PostOrderTraverse(Tree);}图1:二叉树的遍历运行结果第三篇:数据结构二叉树操作验证实验报告班级:计算机11-2 学号:40 姓名:朱报龙成绩:_________实验七二叉树操作验证一、实验目的⑴ 掌握二叉树的逻辑结构;⑵ 掌握二叉树的二叉链表存储结构;⑶ 掌握基于二叉链表存储的二叉树的遍历操作的实现。
数据结构二叉树前驱结点的实验报告二叉树的前驱结点是指在中序遍历中,一个节点的前面那个节点,即左子树中最大的节点。
为了实现二叉树前驱结点的查找,我进行了如下实验。
首先,需要定义二叉树的数据结构。
在这个数据结构中,每个节点包含三个参数:值,左子节点和右子节点。
这个数据结构可以使用递归方式来定义。
接下来,需要定义查找前驱节点所需要的函数。
这个函数的参数是二叉树中的一个节点,函数的返回值是这个节点的前驱节点。
如果这个节点是二叉树中的根节点,那么它没有前驱节点,函数返回 null。
如果这个节点没有左子节点,那么前驱节点一定是它的某个祖先节点。
对于这种情况,可以向上递归,直到找到一个祖先节点,该祖先节点的右子节点是该节点或者该节点的某个祖先节点。
如果这个节点有左子节点,那么前驱节点一定是该节点的左子树中最右边的节点。
对于这种情况,可以向左递归,直到找到最右边的节点。
如果没有左子树,那么该节点的前驱节点就是null。
我实现了这个函数,并在一些测试用例上测试它的效果。
首先,我使用了一个简单的二叉树来进行测试。
这个二叉树包含了三个节点,根节点的值是2,左子节点的值是1,右子节点的值是3、我测试了根节点和右子节点的前驱节点,结果都是左子节点。
接下来,我测试了一个更复杂的二叉树,该二叉树包含了七个节点,是一个完整的二叉树。
我测试了二叉树中每一个节点的前驱节点,结果都是正确的。
通过这个实验,我学习了如何在二叉树中查找前驱节点。
这项技能在很多算法和数据结构中都有很多应用。
通过使用递归的方式,我可以在一些复杂的二叉树中轻松地查找前驱节点。
这种技能对于我今后的编程生涯非常重要,能够帮助我更高效地解决各种问题。
(一)需求和规格说明一棵二叉树可以按照如下规则表示成一个由0、1、2组成的字符序列,我们称之为“二叉树序列S”:例如,下图所表示的二叉树可以用二叉树序列S=21200110来表示。
任务是要对一棵二叉树的节点进行染色。
每个节点可以被染成红色、绿色或蓝色。
并且,一个节点与其子节点的颜色必须不同,如果该节点有两个子节点,那么这两个子节点的颜色也必须不相同。
给定一棵二叉树的二叉树序列,请求出这棵树中最多和最少有多少个点能够被染成绿色。
(二)设计分析过程:这是一道二叉树的染色问题,求染成绿色的最大最小情况,从本质上看,这是一道动态规划问题。
为了方便直观起见,代码开始时用先enum Color{nocolor = 0,green = 1,red = 2,blue = 3};定义了不同的颜色。
举个简单的例子,如下图所示:将整个二叉树划分成三个部分:根节点、左子树、右子树。
由于有约束条件,所以这三个部分存在着互相限制作用如下:1. 二叉树的根节点与左子树的根节点颜色不同;2.二叉树的根节点与右子树的根节点颜色不同;3.左子树根节点与右子树根节点颜色不同。
显然,上述的三个限制表示的是标号为1、2、3三个点之间的互相关系。
除此以外,左子树中的点与右子树中的点没有任何直接的限制关系!也就是说,如果我们事先确定了上述二叉树中标号为1、2、3的三个点的颜色,那么接下来,对左子树染色和对右子树染色将变成两个互不干扰的子问题,左子树最值与右子树最值不影响,可以分开求解。
【互不干扰,可以分开求解】如此一来,通过将三点染色,我们就可以把二叉树分成左右两个子树,整个问题被分解成两个较小规模的子问题。
算法设计:如图二所示,将二叉树划分成三部分,给标号为1、2、3三个点先染色后,将依次处理左子树,右子树。
在求解时,有以下2个问题:(1)染色的任意性标号为1、2、3的三个点的颜色并不一定固定依次是红、绿、蓝。
我们需要对所有染色情况进行枚举,并对每个染色情况进行左、右子树的分别处理。
[精品]【数据结构】二叉树实验报告二叉树实验报告一、实验目的:1.掌握二叉树的基本操作;2.理解二叉树的性质;3.熟悉二叉树的广度优先遍历和深度优先遍历算法。
二、实验原理:1.二叉树是一种树形结构,由n(n>=0)个节点组成;2.每个节点最多有两个子节点,称为左子节点和右子节点;3.二叉树的遍历分为四种方式:前序遍历、中序遍历、后序遍历和层次遍历。
三、实验环境:1.编程语言:C++;2.编译器:Dev-C++。
四、实验内容:1.定义二叉树节点结构体:struct BinaryTreeNode{int data; // 节点数据BinaryTreeNode *leftChild; // 左子节点指针BinaryTreeNode *rightChild; // 右子节点指针};2.初始化二叉树:queue<BinaryTreeNode *> q; // 使用队列存储节点q.push(root);int i = 1; // 创建子节点while (!q.empty() && i < length){BinaryTreeNode *node = q.front();q.pop();if (data[i] != -1) // 创建左子节点 {BinaryTreeNode *leftChild = new BinaryTreeNode;leftChild->data = data[i];leftChild->leftChild = nullptr;leftChild->rightChild = nullptr;node->leftChild = leftChild;q.push(leftChild);}i++;if (data[i] != -1) // 创建右子节点 {BinaryTreeNode *rightChild = new BinaryTreeNode;rightChild->data = data[i];rightChild->leftChild = nullptr;rightChild->rightChild = nullptr;node->rightChild = rightChild;q.push(rightChild);}i++;}return root;}3.前序遍历二叉树:五、实验结果:输入:int data[] = {1, 2, 3, 4, -1, -1, 5, 6, -1, -1, 7, 8};输出:前序遍历结果:1 2 4 5 3 6 7 8中序遍历结果:4 2 5 1 6 3 7 8后序遍历结果:4 5 2 6 8 7 3 1层次遍历结果:1 2 3 4 5 6 7 8通过本次实验,我深入理解了二叉树的性质和遍历方式,并掌握了二叉树的基本操作。
《数据结构与数据库》实验报告实验题目二叉树的基本操作及运算学院:化学与材料科学学院专业班级:09级材料科学与工程系PB0920603姓名:李维谷学号:PB09206285邮箱:liwg@指导教师:贾伯琪实验时间:2010年10月17日一、需要分析问题描述:实现二叉树(包括二叉排序树)的建立,并实现先序、中序、后序和按层次遍历,计算叶子结点数、树的深度、树的宽度,求树的非空子孙结点个数、度为2的结点数目、度为2的结点数目,以及二叉树常用运算。
问题分析:二叉树树型结构是一类重要的非线性数据结构,对它的熟练掌握是学习数据结构的基本要求。
由于二叉树的定义本身就是一种递归定义,所以二叉树的一些基本操作也可采用递归调用的方法。
处理本问题,我觉得应该:1、建立二叉树;2、通过递归方法来遍历(先序、中序和后序)二叉树;3、通过队列应用来实现对二叉树的层次遍历;4、借用递归方法对二叉树进行一些基本操作,如:求叶子数、树的深度宽度等;5、运用广义表对二叉树进行广义表形式的打印。
算法规定:输入形式:为了方便操作,规定二叉树的元素类型都为字符型,允许各种字符类型的输入,没有元素的结点以空格输入表示,并且本实验是以先序顺序输入的。
输出形式:通过先序、中序和后序遍历的方法对树的各字符型元素进行遍历打印,再以广义表形式进行打印。
对二叉树的一些运算结果以整型输出。
程序功能:实现对二叉树的先序、中序和后序遍历,层次遍历。
计算叶子结点数、树的深度、树的宽度,求树的非空子孙结点个数、度为2的结点数目、度为2的结点数目。
对二叉树的某个元素进行查找,对二叉树的某个结点进行删除。
测试数据:输入一:ABC□□DE□G□□F□□□(以□表示空格),查找5,删除E预测结果:先序遍历ABCDEGF中序遍历CBEGDFA后序遍历CGEFDBA层次遍历ABCDEFG广义表打印A(B(C,D(E(,G),F)))叶子数3 深度5 宽度2 非空子孙数6 度为2的数目2 度为1的数目2查找5,成功,查找的元素为E删除E 后,以广义表形式打印A (B (C,D (,F )))输 入 二:ABD □□EH □□□CF □G □□□ (以□表示空格),查找10,删除B 预测结果:先序遍历 ABDEHCFG中序遍历 DBHEAGFC 后序遍历 DHEBGFCA层次遍历 ABCDEFHG广义表打印 A (B(D,E(H)),C(F(,G)))叶子数 3 深度 4 宽度 3 非空子孙数 7 度为2的数目 2 度为1的数目3 查找10,失败。
数据结构实验报告—二叉树数据结构实验报告—二叉树引言二叉树是一种常用的数据结构,它由节点和边构成,每个节点最多有两个子节点。
在本次实验中,我们将对二叉树的基本结构和基本操作进行实现和测试,并深入了解它的特性和应用。
实验目的1. 掌握二叉树的基本概念和特性2. 熟练掌握二叉树的基本操作,包括创建、遍历和查找等3. 了解二叉树在实际应用中的使用场景实验内容1. 二叉树的定义和存储结构:我们将首先学习二叉树的定义,并实现二叉树的存储结构,包括节点的定义和节点指针的表示方法。
2. 二叉树的创建和初始化:我们将实现二叉树的创建和初始化操作,以便后续操作和测试使用。
3. 二叉树的遍历:我们将实现二叉树的前序、中序和后序遍历算法,并测试其正确性和效率。
4. 二叉树的查找:我们将实现二叉树的查找操作,包括查找节点和查找最大值、最小值等。
5. 二叉树的应用:我们将探讨二叉树在实际应用中的使用场景,如哈夫曼编码、二叉搜索树等。
二叉树的定义和存储结构二叉树是一种特殊的树形结构,它的每个节点最多有两个子节点。
节点被表示为一个由数据和指向其左右子节点的指针组成的结构。
二叉树可以分为三类:满二叉树、完全二叉树和非完全二叉树。
二叉树可以用链式存储结构或顺序存储结构表示。
- 链式存储结构:采用节点定义和指针表示法,通过将节点起来形成一个树状结构来表示二叉树。
- 顺序存储结构:采用数组存储节点信息,通过计算节点在数组中的位置来进行访问和操作。
二叉树的创建和初始化二叉树的创建和初始化是二叉树操作中的基础部分。
我们可以通过手动输入或读取外部文件中的数据来创建二叉树。
对于链式存储结构,我们需要自定义节点和指针,并通过节点的方式来构建二叉树。
对于顺序存储结构,我们需要定义数组和索引,通过索引计算来定位节点的位置。
一般来说,初始化一个二叉树可以使用以下步骤:1. 创建树根节点,并赋初值。
2. 创建子节点,并到父节点。
3. 重复步骤2,直到创建完整个二叉树。
⼆叉树基本操作--实验报告实验三⼆叉树的基本操作学院:物理与电⼦学院班级:电信1105班姓名:刘岩学号:29⼀、实验⽬的1、熟悉⼆叉树的基本操作,掌握⼆叉树的实现以及实际应⽤。
3、加深对于⼆叉树的理解,逐步培养解决实际问题的编程能⼒。
⼆、实验环境1台WINDOWS环境的PC机,装有Visual C++ 。
三、实验内容1、问题描述现需要编写⼀套⼆叉树的操作函数,以便⽤户能够⽅便的利⽤这些函数来实现⾃⼰的应⽤。
其中操作函数包括:1>创建⼆叉树CreateBTNode(*b,*str):根据⼆叉树括号表⽰法的字符串*str⽣成对应的链式存储结构。
2>输出⼆叉树DispBTNode(*b):以括号表⽰法输出⼀棵⼆叉树。
3>查找结点FindNode(*b,x):在⼆叉树b中寻找data域值为x的结点,并返回指向该结点的指针。
4>求⾼度BTNodeDepth(*b):求⼆叉树b的⾼度。
若⼆叉树为空,则其⾼度为0;否则,其⾼度等于左⼦树与右⼦树中的最⼤⾼度加l。
5>求⼆叉树的结点个数NodesCount(BTNode *b)6>先序遍历的递归算法:void PreOrder(BTNode *b)7>中序遍历的递归算法:void InOrder(BTNode *b)8>后序遍历递归算法:void PostOrder(BTNode *b)9>层次遍历算法void LevelOrder(BTNode *b)2、基本要求实现以上9个函数。
主函数中实现以下功能:创建下图中的树b输出⼆叉树b找到’H’节点,输出其左右孩⼦值输出b的⾼度输出b的节点个数输出b的四种遍历顺序3、程序编写上图转化为⼆叉树括号表⽰法为A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))程序:#include <>#include <>#define MaxSize 100typedef char ElemType;typedef struct node{ElemType data; /*数据元素*/struct node *lchild; /*指向左孩⼦*/struct node *rchild; /*指向右孩⼦*/} BTNode;void CreateBTNode(BTNode *&b,char *str);//创建BTNode *FindNode(BTNode *b,ElemType x);//查找节点int BTNodeHeight(BTNode *b);//求⾼度void DispBTNode(BTNode *b);//输出int NodesCount(BTNode *b);//⼆叉树的结点个数void PreOrder(BTNode *b);//先序遍历递归void InOrder(BTNode *b);//中序遍历递归void PostOrder(BTNode *b);//后序遍历递归void LevelOrder(BTNode *b);//层次遍历//创建void CreateBTNode(BTNode *&b,char *str){BTNode *St[MaxSize],*p=NULL;int top=-1,k,j=0;char ch;b=NULL;ch=str[j];while(ch!='\0'){switch(ch){case '(':top++;St[top]=p;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){case 1:St[top]->lchild=p;break;case 2:St[top]->rchild=p;break;}}}j++;ch=str[j];}}//输出void DispBTNode(BTNode *b){if(b!=NULL){printf("%c",b->data);if(b->lchild!=NULL||b->rchild!=NULL){printf("(");DispBTNode(b->lchild);if(b->rchild!=NULL)printf(",");DispBTNode(b->rchild);printf(")");}}}//查找节点BTNode *FindNode(BTNode *b,ElemType x){ BTNode *p;if(b==NULL)return b;else if(b->data==x)return b;else{p=FindNode(b->lchild,x);if(p!=NULL)return p;elsereturn FindNode(b->rchild,x);}}//求⾼度int BTNodeHeight(BTNode *b){int lchildh,rchildh;if(b==NULL)return (0);else{lchildh=BTNodeHeight(b->lchild);rchildh=BTNodeHeight(b->rchild);return(lchildh>rchildh)(lchildh+1):(rchildh+1);}}//⼆叉树的结点个数int NodesCount(BTNode *b){if(b==NULL)return 0;elsereturn NodesCount(b->lchild)+NodesCount(b->rchild)+1; }//先序遍历递归void PreOrder(BTNode *b){ if(b!=NULL){printf("%c",b->data); PreOrder(b->lchild); PreOrder(b->rchild);}}//中序遍历递归void InOrder(BTNode *b){if(b!=NULL){InOrder(b->lchild);printf("%c",b->data); InOrder(b->rchild);}}//后序遍历递归void PostOrder(BTNode *b){ if(b!=NULL){PostOrder(b->lchild); PostOrder(b->rchild);printf("%c",b->data);}}//层次遍历void LevelOrder(BTNode *b){ BTNode *p;BTNode *qu[MaxSize];int front,rear;front=rear=-1;rear++;qu[rear]=b;while(front!=rear){front=(front+1)%MaxSize;p=qu[front];printf("%c",p->data);if(p->lchild!=NULL){rear=(rear+1)%MaxSize;qu[rear]=p->lchild;}if(p->rchild!=NULL){rear=(rear+1)%MaxSize;qu[rear]=p->rchild;}}}void main(){BTNode *b,*p,*lp,*rp;char str[]="A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))";//根据树形图改写成的//⼆叉树括号表⽰法的字符串*str //char str[100];scanf("%s",&str);//⾃⾏输⼊括号表⽰的⼆叉树CreateBTNode(b,str); //创建树bprintf("\n");printf("输出⼆叉树:");//输出⼆叉树bDispBTNode(b);printf("\n");printf("'H'结点:");//找到'H'节点,输出其左右孩⼦值p=FindNode(b,'H');printf("\n");if (p!=NULL){printf("左孩⼦节点的值");printf("%c",p->lchild->data);printf("\n");printf("右孩⼦节点的值");printf("%c",p->rchild->data);printf("\n");//此处输出p的左右孩⼦节点的值}printf("\n");printf("⼆叉树b的深度:%d\n",BTNodeHeight(b));//输出b的⾼度printf("⼆叉树b的结点个数:%d\n",NodesCount(b));//输出b的节点个数printf("\n");printf(" 先序遍历序列:\n");//输出b的四种遍历顺序printf(" 算法:");PreOrder(b);printf("\n");printf(" 中序遍历序列:\n");printf(" 算法:");InOrder(b);printf("\n");printf(" 后序遍历序列:\n");printf(" 算法:");PostOrder(b);printf("\n");printf(" 层次遍历序列:\n");printf(" 算法:");LevelOrder(b); printf("\n");}四、实验⼼得与⼩结通过本次实验,我熟悉⼆叉树的基本知识内容,对课本的知识有了更加深刻的理解与掌握掌握。
实验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.按凹入表形式打印树形结构。
三、数据结构设计1.对于二叉树来说,每个节点最多有两个孩子,采用链式方式存储,每个结点的值域有数据域(data),两个指针域左海子(lchild)右孩子(rchild),该结点的深度(degree)。
但是如果打印二叉树的话则每个节点的深度规定根节点的深度为0,其孩子结点的深度为1并且兄弟节点的深度是相同的,则二叉树结点的结构为data lchild rchild degree2.对与树使用孩子---兄弟的数据结构即每个结点有两个域为指向孩子节点(firstchild)和下个兄弟域(nextsibling)firstchild nextsibling三.功能设计1.二叉树的算法思想(1)对二叉树的遍历用递归思想,改变访问根节点的顺序来实施遍历。
(2)如果打印二叉树则需要构造完全二叉树,若空结点,用相同的变量的代替。
遍历的时候是先遍历右子树的中序遍历。
建立的时候先建立一个根结点,若不是空的话,则为其孩子节点,重复操作直到建立完整的二叉树。
(3)打印树在遍历是的时候用先根遍历。
建立需要使用队列的数据结构相结合存储树。
编码实现四、运行与调试一.先序遍历二.中序遍历三.递归后续遍历二叉树四.打印二叉树五.打印树五、实验完成后的思考1.遍历二叉树的过程注意基本c语言语句的书写,此外建立二叉树的时候首先申请一个空间。
最重的是要弄清楚在输入二叉树时结束符,和空字符的位置。
题目:编程实现二叉查找树的建立、中序遍历、元素查找等功能,要求解释实现过程及演示实际例子的运行结果。
算法描述:首先创建二叉树结点类,其主要包括:二叉树结点数据域,指向左、右子树的指针,构造函数,设置当前结点左、右子树、数据域以及判断当前结点是否为叶子结点等。
然后进行二叉树类定义,其私有部分为定义二叉树根结点指针,公有部分主要包括:构造函数、析构函数、判断二叉树是否为空树、先,中,后序遍历的递归与非递归、二叉树删除、层序遍历以及二叉树搜索等。
接下来将对一些重要函数算法进行描述:1、isLeaf函数:若该结点的左子树和右子树都为空,则为叶子结点。
2、isEmpty函数:根结点为空则为空树。
3、Parent函数:首先判断给定结点是否有双亲,根结点和空结点一定无双亲,初始化一个临时变量,用于跟进查找双亲结点,查找到后其保存的便是双亲结点。
先递归在左子树中查找,如果找到,便结束递归且返回双亲结点指针;如果没有找到,再递归在右子树中查找。
如果都没有找到,说明给定结点的双亲结点不在该二叉树中。
4、LeftSibling(RightSibling)函数:首先找到当前结点的双亲,然后判断双亲结点左右子树是否为空,其中必然有一个不为空,返回另一个子树指针即可。
5、DeleteBinaryTree函数:首先判断是否为空树,若为空,则返回,然后递归删除左子树,递归删除右子树,最后删除根结点。
6、PreOrder函数:首先判断是否为空树,若为空,则返回,然后访问根结点,递归遍历左子树,递归遍历右子树,结束。
7、PreOrderWithoutRecusion函数:使用栈来模拟递归过程,首先申请栈,用于保存结点指针序列,申请指针pointer保存当前根指针,然后判断栈是否为空,若栈为空且pointer为空,跳出函数,否则若pointer不为空,访问pointer所指结点,pointer入栈,pointer指向其左子树;若pointer为空,弹出栈顶元素赋给pointer,pointer指向其右子树,结束。
二叉树实现及应用实验报告实验名称:二叉树实现及应用实验目的:1. 实现二叉树的创建、插入和删除操作。
2. 学习二叉树的遍历方法,并能够应用于实际问题。
3. 掌握二叉树在数据结构和算法中的一些常用应用。
实验内容:1. 实现二叉树的创建、插入和删除操作,包括二叉树的构造函数、插入函数和删除函数。
2. 学习二叉树的三种遍历方法:前序遍历、中序遍历和后序遍历,并应用于实际问题。
3. 掌握二叉树的一些常用应用,如二叉搜索树、平衡二叉树和哈夫曼树等。
实验步骤:1. 创建二叉树的结构体,包括树节点和树的根节点。
2. 实现二叉树的构造函数,用于创建二叉树的根节点。
3. 实现二叉树的插入函数,用于将元素插入到二叉树中的合适位置。
4. 实现二叉树的删除函数,用于删除二叉树中的指定元素。
5. 学习并实现二叉树的前序遍历、中序遍历和后序遍历函数。
6. 运用二叉树的遍历方法解决实际问题,如查找二叉树中的最大值和最小值。
7. 学习并应用二叉搜索树、平衡二叉树和哈夫曼树等常用二叉树结构。
实验结果:1. 成功创建、插入和删除二叉树中的元素,实现了二叉树的基本操作。
2. 正确实现了二叉树的前序遍历、中序遍历和后序遍历,并能够正确输出遍历结果。
3. 通过二叉树的遍历方法成功解决了实际问题,如查找二叉树中的最大值和最小值。
4. 学习并熟练应用了二叉搜索树、平衡二叉树和哈夫曼树等常用二叉树结构,丰富了对二叉树的理解。
实验分析:1. 二叉树是一种重要的数据结构,具有较好的数据存储和查找性能,广泛应用于计算机科学和算法领域。
2. 通过实验,我们深入了解了二叉树的创建、插入和删除操作,以及前序遍历、中序遍历和后序遍历的原理和应用。
3. 实际问题往往可以转化为二叉树的遍历问题进行求解,通过实验,我们成功应用了二叉树的遍历方法解决了实际问题。
4. 熟练掌握二叉搜索树、平衡二叉树和哈夫曼树的原理和应用,对于提高我们在数据结构和算法方面的设计能力具有重要意义。
东华理工大学实验、实习报告姓名(学号):所在组别:7-1 实验题目:统计二叉树的结点数和叶子结点数实验时间:2014.10.30 实验地点:软件楼一、实验目的深入了解的二叉树的基本操作(二叉树的创建以及统计结点数和叶子结点数)及其运用二、实验内容1.编写一程序,统计出二叉树的结点数和叶子结点数三、实验步骤#include<stdio.h>#include<stdlib.h>#include<iostream>using namespace std;int C=0,C3=0;//二叉链表存储定义typedef struct bitnode{char data;struct bitnode*rchild,*lchild;}bitnode,*bitree;//创建二叉树void createbitree(bitree&T){int i=0,j=0;char e;cin>>e;C=C+1;if(e=='#'){T=NULL;C3=C3+1;}else{T=(bitree)malloc(sizeof(bitnode));T->data=e;createbitree(T->lchild);createbitree(T->rchild);}}//统计二叉树叶子结点int countleaf(bitree&T){int countleft,countright,C2;if(!T)return0;if(T->lchild==NULL&&T->rchild==NULL) {C2=0;return1;}countleft=countleaf(T->lchild);countright=countleaf(T->rchild);C2=countleft+countright;return C2;};//主函数void main(){bitree T;int C1=0,C2;cout<<"请输入二叉树:";createbitree(T);C2=countleaf(T);if(C!=3){C1=C-C2-C3;cout<<"二叉树的结点数:"<<C1<<endl;cout<<"二叉树的叶子结点数:"<<C2<<endl;}else{C1=1;cout<<"二叉树的结点数:"<<C1<<endl;cout<<"二叉树的叶子结点数:"<<C2<<endl;}四、实验结果特殊情况(只有一个根结点存在的):普通情况:五、小组成员参和实验情况表成员角色完成的内容xxx 编写程序xxx 编写程序xxx 编写程序,整理Word通过实验可以增强对二叉树的理解和所学知识的灵活运用,增强自我学习能力和团队的合作精神。
数据结构实验报告—二叉树目录1. 引言1.1 背景1.2 目的2. 前期准备2.1 问题定义2.2 数据准备3. 算法设计3.1 插入节点3.2 删除节点3.3 查找节点3.4 遍历二叉树4. 实验过程4.1 实验环境4.2 实验步骤5. 实验结果与分析5.1 插入节点的结果 5.2 删除节点的结果 5.3 查找节点的结果5.4 遍历二叉树的结果6. 总结与讨论6.1 实验总结6.2 实验改进方向7. 结论8. 参考文献1. 引言1.1 背景介绍二叉树的概念和应用领域,以及在数据结构中的重要性。
1.2 目的明确本实验的目标,即设计一个能够实现插入、删除、查找和遍历二叉树的算法,并对其进行实验验证。
2. 前期准备2.1 问题定义对二叉树的基本操作进行定义,包括插入节点、删除节点、查找节点和遍历二叉树。
2.2 数据准备准备一组用于测试的数据集,包括插入节点、删除节点和查找节点时所需的数据。
3. 算法设计3.1 插入节点详细描述如何设计实现插入节点的算法,并分析算法的时间复杂度和空间复杂度。
3.2 删除节点详细描述如何设计实现删除节点的算法,并分析算法的时间复杂度和空间复杂度。
3.3 查找节点详细描述如何设计实现查找节点的算法,并分析算法的时间复杂度和空间复杂度。
3.4 遍历二叉树详细描述如何设计实现遍历二叉树的算法,并分析算法的时间复杂度和空间复杂度。
4. 实验过程4.1 实验环境描述实验所用的编程语言和相关工具的环境配置。
4.2 实验步骤详细描述实验的具体步骤,包括数据准备、算法实现、代码编写、实验运行和结果分析等。
5. 实验结果与分析5.1 插入节点的结果展示插入节点的实验结果,并对结果进行详细分析和讨论。
5.2 删除节点的结果展示删除节点的实验结果,并对结果进行详细分析和讨论。
5.3 查找节点的结果展示查找节点的实验结果,并对结果进行详细分析和讨论。
5.4 遍历二叉树的结果展示遍历二叉树的实验结果,并对结果进行详细分析和讨论。
二叉树实验报告总结(共10篇)二叉树实验报告实验报告课程名称算法与数据结构专业学号姓名实验日期算法与数据结构实验报告一、实验目的1.了解二叉树的结构特点及有关概念,掌握二叉树建立的基本算法2.了解二叉树遍历的概念,掌握遍历二叉的算法3.进一步掌握树的结构及非线性特点,递归特点和动态性。
二、实验内容二叉树的实现和运算三、实验要求1.用C++/C完成算法设计和程序设计并上机调试通过。
2.撰写实验报告,提供实验结果和数据。
3.分析算法,并简要给出算法设计小结和心得。
四、算法步骤用户以三元组形式输入二叉树的结点元素及其位置关系,建立二叉树,并打印输出该二叉树。
用户输入选择结点,程序调用BiTNode* Find Node(char tag, BiTNode* node)函数,返回子树的根结点,然后调用BiTreeDepth(BiTree T)函数,求出子树的深度,并输出该值。
3.用户可以选择是否继续执行程序,若继续,则输入1,否则输入0,结束程序。
五、主程序代码:int main(void){BiTree T;TElemType e1;char node; // node为用户选择输入的结点//int b,choose; // b为以选定结点为子树的深度,choose为实现多次选择输入的标志//BiTNode* a; // a为选定结点为子树的根结点//choose=1; // 多次选择的标志,当choose为1时运行程序,为0时结束程序// InitBiTree(T);printf(构造空二叉树后,树空否?%d(1:是0:否), 树的深度=%d\n,BiTreeEmpty(T),BiTreeDepth(T));e1 = Root(T);if(e1 != Nil)#ifdef CHARprintf(二叉树的根为: %c\n,e1);#endif#ifdef INTprintf(二叉树的根为: %d\n,e1);#endifelseprintf(树空,无根\n); //三元组构建二叉树striile(x!=end){AddNode(T, x[0], x[1], x[2]);GetUserWord(x);} //输出树PrintTreeLevel( T );//以三元组形式输入任意二叉树(以大写字母表示结点),求以任意一选定结点为子树的深度。
课程设计报告设计题目:二叉树结点染色问题学生姓名:专业:计算机科学与技术班级:学号:指导教师:完成日期:2015-7-7(一)需求和规格说明一棵二叉树可以按照如下规则表示成一个由0、1、2组成的字符序列,我们称之为“二叉树序列S”:例如,下图所表示的二叉树可以用二叉树序列S=21200110来表示。
任务是要对一棵二叉树的节点进行染色。
每个节点可以被染成红色、绿色或蓝色。
并且,一个节点与其子节点的颜色必须不同,如果该节点有两个子节点,那么这两个子节点的颜色也必须不相同。
给定一棵二叉树的二叉树序列,请求出这棵树中最多和最少有多少个点能够被染成绿色。
(二)设计分析过程:这是一道二叉树的染色问题,求染成绿色的最大最小情况,从本质上看,这是一道动态规划问题。
为了方便直观起见,代码开始时用先enum Color{nocolor = 0,green = 1,red = 2,blue = 3};定义了不同的颜色。
举个简单的例子,如下图所示:将整个二叉树划分成三个部分:根节点、左子树、右子树。
由于有约束条件,所以这三个部分存在着互相限制作用如下:1. 二叉树的根节点与左子树的根节点颜色不同;2.二叉树的根节点与右子树的根节点颜色不同;3.左子树根节点与右子树根节点颜色不同。
显然,上述的三个限制表示的是标号为1、2、3三个点之间的互相关系。
除此以外,左子树中的点与右子树中的点没有任何直接的限制关系!也就是说,如果我们事先确定了上述二叉树中标号为1、2、3的三个点的颜色,那么接下来,对左子树染色和对右子树染色将变成两个互不干扰的子问题,左子树最值与右子树最值不影响,可以分开求解。
【互不干扰,可以分开求解】如此一来,通过将三点染色,我们就可以把二叉树分成左右两个子树,整个问题被分解成两个较小规模的子问题。
算法设计:如图二所示,将二叉树划分成三部分,给标号为1、2、3三个点先染色后,将依次处理左子树,右子树。
在求解时,有以下2个问题:(1)染色的任意性标号为1、2、3的三个点的颜色并不一定固定依次是红、绿、蓝。
数据结构实验报告实验名称:实验三——二叉树学生姓名: XX班级:班内序号:学号:日期:1.实验要求1.1实验目的通过选择下面两个题目之一进行实现,掌握如下内容:掌握二叉树基本操作的实现方法了解赫夫曼树的思想和相关概念学习使用二叉树解决实际问题的能力1.2实验内容根据二叉树的抽象数据类型的定义,使用二叉链表实现一个二叉树。
二叉树的基本功能:1、二叉树的建立2、前序遍历二叉树3、中序遍历二叉树4、后序遍历二叉树5、按层序遍历二叉树6、求二叉树的深度7、求指定结点到根的路径8、二叉树的销毁9、其他:自定义操作编写测试main()函数测试线性表的正确性2. 程序分析2.1 存储结构二叉树的结点结构二叉树的二叉链表存储示意图2.2 关键算法分析(1)创建一个二叉树伪代码实现:1.定义根指针,输入节点储存的data,若输入“#”,则该节点为空;2.申请一个新节点,判断它的父结点是否不为空,如果不为空在判断其为左或者右孩子,并把地址付给父结点,把data写入。
代码实现void BiTree::create(BiNode* &R,int data[],int i,int n)//创建二叉树{if(i<=n){R=new BiNode;R->data=data[i-1];create(R->lch,data,2*i,n);create(R->rch,data,2*i+1,n);}else R=NULL;}(2)前序遍历伪代码实现:1.设置递归边界条件:if root==null则停止递归2.打印起始节点的值,并先后在左子数右子数上递归调用打印函数代码实现void BiTree::preorder(BiNode* R)//前序遍历{if(R!=NULL){cout<<R->data;preorder(R->lch);preorder(R->rch);}}时间复杂度:O(n)(3)中序遍历伪代码实现:1.设置递归边界条件:if root==null则停止递归2.递归遍历左子树3.打印根节点数据域内容4.递归遍历右子树代码实现void BiTree::inorder(BiNode* R)//中序遍历{if(R!=NULL){inorder(R->lch);cout<<R->data;inorder(R->rch);}}时间复杂度:O(n)(4)后序遍历伪代码实现:1.设置递归边界条件:if root==null则停止递归2.递归遍历左子树3.递归遍历右子树4.访问根结点数据域代码实现void BiTree::postorder(BiNode* R)//后序遍历{if(R!=NULL){postorder(R->lch);postorder(R->rch);cout<<R->data;}}时间复杂度:O(n)(5)层序遍历伪代码实现1.队列Q及所需指针的定义和初始化2.如果二叉树非空,将根指针入队3.循环直到队列Q为空3.1 q=队列Q的队头元素出队3.2 访问节点q的数据域 cout<<q->data<<" ";3.3 若节点q存在左孩子,则将左孩子指针入队3.4若节点q存在右孩子,则将右孩子指针入队代码实现void BiTree::levelordre(BiNode* R)//层序遍历{BiNode*queue[maxsize];int f=0,r=0;if(R!=NULL)queue[++r]=R;while(f!=r){BiNode*p=queue[++f];cout<<p->data;if(p->lch!=NULL)queue[++r]=p->lch;if(p->rch!=NULL)queue[++r]=p->rch;}}时间复杂度:O(n)(6)计算二叉树深度伪代码实现:1. 定义和初始化计数深度的参数2.如果根节点为空,return03.如果根节点为非空,递归调用自身的到叶子节点到根的路径长度,输出其中较大的作为树的深度代码实现int BiTree::depth(BiNode* root)//求二叉树深度{int ld,rd;if (root!=NULL){ld = 1+depth(root->lch);rd = 1+depth(root->rch);return ld>rd?ld:rd;}else return 0;}时间复杂度:O(n)(7)输出指定结点到根结点的路径伪代码实现:1.建立一个存储路径结点结构,定义和初始化结构体的数组2.当root不为空或top为0时,进入循环3.当此时root所指的节点的数据不为指定数据时,将root指向它的左孩子4.当此时root所指的节点的数据为指定数据时,访问其数据域并输出代码实现bool BiTree::printPath(BiNode* root, int data)//打印指定结点到根节点的路径{if (root == NULL)return false;if (root->data == data || printPath(root->lch,data) ||printPath(root->rch,data)){cout<<root->data;return true;}return false;}3. 程序运行结果3.1测试主函数流程图:3.2测试条件对如下二叉树: 补全后的二叉树:按层序遍历的输入方法为:ABC#EFGH###I###J###@ 3.3程序运行结果为:4. 总结出现的问题及改进:刚开始编译正确但是输出结果异常,纪念馆仔细检查发现二叉树创建有问题,经过仔细修改,发现形参表示错误,*&,指针的引用,作为输入时,既把指针的值传入函数内部,又可以将指针的关系传递到函数内部;作为输出,由于算法中修改了指针的值,可以将新值传入到函数内部。
(一)需求和规格说明一棵二叉树可以按照如下规则表示成一个由0、1、2组成的字符序列,我们称之为“二叉树序列S”:例如,下图所表示的二叉树可以用二叉树序列S=21200110来表示。
任务是要对一棵二叉树的节点进行染色。
每个节点可以被染成红色、绿色或蓝色。
并且,一个节点与其子节点的颜色必须不同,如果该节点有两个子节点,那么这两个子节点的颜色也必须不相同。
给定一棵二叉树的二叉树序列,请求出这棵树中最多和最少有多少个点能够被染成绿色。
(二)设计分析过程:这是一道二叉树的染色问题,求染成绿色的最大最小情况,从本质上看,这是一道动态规划问题。
为了方便直观起见,代码开始时用先enum Color{nocolor = 0,green = 1,red = 2,blue = 3};定义了不同的颜色。
举个简单的例子,如下图所示:将整个二叉树划分成三个部分:根节点、左子树、右子树。
由于有约束条件,所以这三个部分存在着互相限制作用如下:1. 二叉树的根节点与左子树的根节点颜色不同;2.二叉树的根节点与右子树的根节点颜色不同;3.左子树根节点与右子树根节点颜色不同。
显然,上述的三个限制表示的是标号为1、2、3三个点之间的互相关系。
除此以外,左子树中的点与右子树中的点没有任何直接的限制关系!也就是说,如果我们事先确定了上述二叉树中标号为1、2、3的三个点的颜色,那么接下来,对左子树染色和对右子树染色将变成两个互不干扰的子问题,左子树最值与右子树最值不影响,可以分开求解。
【互不干扰,可以分开求解】如此一来,通过将三点染色,我们就可以把二叉树分成左右两个子树,整个问题被分解成两个较小规模的子问题。
算法设计:如图二所示,将二叉树划分成三部分,给标号为1、2、3三个点先染色后,将依次处理左子树,右子树。
在求解时,有以下2个问题:(1)染色的任意性标号为1、2、3的三个点的颜色并不一定固定依次是红、绿、蓝。
我们需要对所有染色情况进行枚举,并对每个染色情况进行左、右子树的分别处理。
同样,当根节点只有一个子节点时,我们也要枚举此时的染色方案。
(2)根节点的颜色已确定由于2号点已经染色,所以,在递归处理左子树时,问题就转化成“根节点颜色已确定,求满足约束条件的最多(最小)染色方案”。
这个转化后的子问题与原问题略有差异:原问题中根节点可以任意染色,而转化后的子问题中根节点的颜色是固定的。
为了便于递归调用相同的处理操作,我们必须保证所有问题的条件与求解目标的统一!于是,有必要将原问题稍做修改:事先求出整个二叉树根节点为红色、绿色或蓝色情况下问题的解(这就与子问题是同一类型了),然后取这三个解中的最大(或最小)值,即得到原问题的解。
分析至此,我们已经得出了解决问题的大致方法:将原问题转化成“根节点颜色确定,求染色最值方案”;枚举根节点的左节点与右节点(如果存在)的颜色,同时满足约束条件;对每种染色方案,递归处理求左、右两子树。
给二叉树上所有节点标号,从1~N;用son记录二叉树的构造关系, Son(i,0)和Son(i,1)分别表示编号是i的节点,其左右两个子节点的编号(如果不存在,则用-1表示)。
例如在上图中,我们有Son(1,0)=2,Son(1,1)=3。
用F(i,j)表示一个子问题一个子问题可以由两个参数来描述:根节点编号i,根节点颜色j。
F(i , j)表示:以编号是i、颜色是j的节点为根节点的子树,在满足约束条件的情况下染色,绿色节点最多(最少)有多少个。
按照先前所设计的算法,可以大致得出如下式:0 i == -1F(i,j) = F(son(i,0), j1)+F (son(i,1),j2) i<>-1 j<>green F(son(i,0),j1)+ F(son(i,1),j2+1 i<>-1 j == green根据我们的分析,算法会有重复操作,多次计算F(i,j)的值。
那么,我们不妨造一个表将F(i,j)保存起来,这样就能有效避免重复计算了。
类型成员名描述结构体名成员类别node 属性int ChildNum 存储当前结点拥有的孩子值,Color color 存储当前结点的颜色类名成员类别类型成员名描述employee 属性int length S的长度node的动态数组tree 存储tree的结点方法TREE() 构建treevoid Preorder(inti) 以第i结点为根结点进行先序遍历int Son(int i ,boolright)返回第i个结点的孩子,第二个参数表示返回是左孩子还是右孩子,若没有,返回-1int GreenMax() 求最多有多少个绿色结点并返回int GreenMin() 求最少有多少个绿色结点并返回int Max(inti,Color j,intmermory[]) 求以第i个结点在颜色j下为根结点时最多有多少个绿色结点并返回int Min(inti,Color j,intmermory[]) 求以第i个结点在颜色j下为根结点时最少有多少个绿色结点并返回时间复杂度从一棵树的根结点开始,依次求解结点的子树最多/少有多少的结点可以染成绿色,若树有n个结点,那么复杂度为O(n)。
(三)用户手册用户通过修改TREE.TRE文本文档中二叉序列S来构造不同的二叉树,-1表示S结束。
运行第一行表示读入的s的值。
第二行先序遍历来验证生成的树是否正确之后给出结果:绿色结点最多有多少个:绿色结点最少有多少个:(四)调试及测试运行实例:附录 源程序#include <iostream>#include"tree.h"using namespace std;int main(){Tree Tree;cout << endl << "先序遍历:" << endl;tree.preorder(tree.root);cout << endl;cout << "绿色结点最多有:";cout << tree.GreenMax() << endl;cout << "绿色结点最少有:";cout << tree.GreenMin() << endl;return 0;}tree.henum Color{nocolor = 0,green = 1,red = 2,blue = 3};struct node{int ChildNum;Color color;};class TREE{public:int length;node *tree = new node[length * 2 + 2];TREE();void preorder(int i); //先序遍历int son(int i, bool rigth);int GreenMax();int GreenMin();int Max(int i, Color j,int memory[]);int Min(int i, Color j,int memory[]);};tree.cpp#include <fstream>#include<iostream>#include"tree.h"using namespace std;TREE::TREE(){ifstream s;s.open("TREE.TRE"); //通过打开“TREE.TRE”文件来构造一个树if (!s){cout << "打开文件错误!";exit(0);}int ChildNum;int length = 0;node *tree = new node[length * 2 + 1];s >> ChildNum;cout << "读入的S=";while (ChildNum != -1){cout << ChildNum;length++;switch (ChildNum){case'0':tree[length].ChildNum = 0;tree[length * 2].ChildNum = -1; //-1表示该结点为空tree[length * 2 + 1].ChildNum = -1;break;case'1':tree[length].ChildNum = 1;tree[length * 2 + 1].ChildNum = -1;break;case '2':tree[length].ChildNum = 2;break;}s >> ChildNum;}}int TREE::son(int i, bool rigth){if (rigth){if (tree[i * 2 + 1].ChildNum == -1)return -1;else return i * 2 + 1;}else{if (tree[2 * i].ChildNum == -1)return -1;else return i * 2;}}int TREE::GreenMax(){int * temp = new int [3 * length + 1]; //temp来记录以及求过的结点,避免重复运算for (int i = 1; i < 3 * length + 1; i++)temp[i] = -1;int a = Max(1, green,temp);int b = Max(1, red,temp);int c = Max(1, blue,temp);return a >(b = b > c ? b : c) ? a : b;}int TREE::Max(int i, Color j,int memory[]){int t = 3 * (i - 1) + j;if (memory[t] == -1){if (i = -1)memory[t] = 0;else{if (j != green)memory[t] = Max(son(i, 0), Color((j + 1) % 3), memory) + Max(son(i, 1), Color((j + 1) % 3), memory);else memory[t] = Max(son(i, 0), Color((j + 1) % 3), memory) + Max(son(i, 1), Color((j + 1) % 3), memory) + 1;}}return memory[t];}int TREE::GreenMin(){int * temp = new int [3 * length + 1]; /for (int i = 1; i < 3 * length + 1; i++)temp[i] = -1;int a = Min(1, green,temp);int b = Min(1, red,temp);int c = Min(1, blue,temp);return a <(b = b < c ? b : c) ? a : b;}int TREE::Min(int i, Color j,int memory[])int t = 3 * (i - 1) + j;if (memory[t] == -1){if (i = -1)memory[t] = 0;else{if (j != green)memory[t] = Min(son(i, 0), Color((j + 1) % 3), memory) + Min(son(i, 1), Color((j + 1) % 3), memory);else memory[t] = Min(son(i, 0), Color((j + 1) % 3), memory) + Min(son(i, 1), Color((j + 1) % 3), memory) + 1;}}return memory[t];}void TREE::preorder(int i){if (i > 0 && i < 2 * length + 1){cout << tree[i].ChildNum << " ";preorder(i * 2);preorder(i * 2 + 1);}}。