已知前序和中序、后序和中序建立二叉树
2015-04-12 23:38
274 查看
首先明确先序遍历的顺序为:根结点→左结点→右结点;中序遍历的顺序为:左结点→根结点→右结点;后序遍历的顺序为:左结点→右结点→根结点。
1. 给定先序和中序建立二叉树。
1) 函数原型:
void CreateByPreAndIn(BinaryTree &T,charpreorder[],char inorder[],int first,int last)
2) 参数说明:
T是当前要建立的二叉树结点;
preorder是先序遍历的数组;inorder是中序遍历的数组;
first是以T为根结点的树中所有元素在inorder数组的最左下标,last是最右下标
3) 算法描述:
由于二叉树是递归定义的,遍历也是递归进行的,因此,递归建树比较方便。
假设当前要建立的二叉树的根结点在preorder中的下标为index(对整棵树而言index=0),当前要建立的二叉树在inorder中的范围为[first,last](对整棵树而言,自然就是[0,strlen(inorder)-1]),当前根结点在inorder中的下标为loc。
对当前要建立的二叉树结点T(当前树的根结点):
若first>last:该结点不存在,即T=NULL;
若first==last:该结点存在,分配内存,T->data=preorder[index],但是该结点没有左右子结点,即T->leftchild=T->rightchild=NULL,继续向下建立下一个结点,即index++;
若first<last:该结点存在且左右子结点至少存在一个,那么T->data=preorder[index],index++后,由于先序遍历的顺序为:根结点→左结点→右结点,所以下一个首先建立左子结点(相对于结点T而言),然后建立右子结点。由于中序遍历的顺序为:左结点→根结点→右结点,所以inorder中的[first,loc-1]均为T的左子树结点,[loc+1,last]均为T的右子树节点,所以调用 CreateByPreAndIn(T->leftchild,preorder,inorder,first,loc-1)和
CreateByPreAndIn(T->rightchild,preorder,inorder,loc+1,last)建立T的左右子树。
2. 给定后序和中序建立二叉树。
1) 函数原型:
voidCreateByPostAndIn(BinaryTree &T,char postorder[],char inorder[],intfirst,int last)
2) 参数说明:
postorder是先序遍历的数组,其余同上。
3) 算法描述:
基本同上,区别在于上个算法中index从0加到strlen(preorder)-1,当first<last时,建立完结点T后,首先建立左子结点(相对于结点T而言),然后建立右子结点。而本算法由于给定后序,整棵树的根结点在后序遍历的最后,所以index应该从strlen(postorder)-1减到0,当first<last时,建立完结点T后,首先建立的应该是右子结点(相对于结点T而言),然后建立左子结点,这是因为index从大向小递减,而后序遍历为左、右、根,为保持与index同样的顺序,所以应该按照根(T本身)、右、左的顺序来建立二叉树。
3. 注意:给定前序和后序无法求出唯一的二叉树。
举例如下:
树A:有结点1,2,3,2是1的左孩子,3是2的右孩子
树B:有结点1,2,3,2是1的右孩子,3是2的左孩子
则A,B的前序都是123,后序都是321,但A的中序是231,B的中序是132.
1. 给定先序和中序建立二叉树。
1) 函数原型:
void CreateByPreAndIn(BinaryTree &T,charpreorder[],char inorder[],int first,int last)
2) 参数说明:
T是当前要建立的二叉树结点;
preorder是先序遍历的数组;inorder是中序遍历的数组;
first是以T为根结点的树中所有元素在inorder数组的最左下标,last是最右下标
3) 算法描述:
由于二叉树是递归定义的,遍历也是递归进行的,因此,递归建树比较方便。
假设当前要建立的二叉树的根结点在preorder中的下标为index(对整棵树而言index=0),当前要建立的二叉树在inorder中的范围为[first,last](对整棵树而言,自然就是[0,strlen(inorder)-1]),当前根结点在inorder中的下标为loc。
对当前要建立的二叉树结点T(当前树的根结点):
若first>last:该结点不存在,即T=NULL;
若first==last:该结点存在,分配内存,T->data=preorder[index],但是该结点没有左右子结点,即T->leftchild=T->rightchild=NULL,继续向下建立下一个结点,即index++;
若first<last:该结点存在且左右子结点至少存在一个,那么T->data=preorder[index],index++后,由于先序遍历的顺序为:根结点→左结点→右结点,所以下一个首先建立左子结点(相对于结点T而言),然后建立右子结点。由于中序遍历的顺序为:左结点→根结点→右结点,所以inorder中的[first,loc-1]均为T的左子树结点,[loc+1,last]均为T的右子树节点,所以调用 CreateByPreAndIn(T->leftchild,preorder,inorder,first,loc-1)和
CreateByPreAndIn(T->rightchild,preorder,inorder,loc+1,last)建立T的左右子树。
2. 给定后序和中序建立二叉树。
1) 函数原型:
voidCreateByPostAndIn(BinaryTree &T,char postorder[],char inorder[],intfirst,int last)
2) 参数说明:
postorder是先序遍历的数组,其余同上。
3) 算法描述:
基本同上,区别在于上个算法中index从0加到strlen(preorder)-1,当first<last时,建立完结点T后,首先建立左子结点(相对于结点T而言),然后建立右子结点。而本算法由于给定后序,整棵树的根结点在后序遍历的最后,所以index应该从strlen(postorder)-1减到0,当first<last时,建立完结点T后,首先建立的应该是右子结点(相对于结点T而言),然后建立左子结点,这是因为index从大向小递减,而后序遍历为左、右、根,为保持与index同样的顺序,所以应该按照根(T本身)、右、左的顺序来建立二叉树。
3. 注意:给定前序和后序无法求出唯一的二叉树。
举例如下:
树A:有结点1,2,3,2是1的左孩子,3是2的右孩子
树B:有结点1,2,3,2是1的右孩子,3是2的左孩子
则A,B的前序都是123,后序都是321,但A的中序是231,B的中序是132.
/* 数据结构分析与学习专栏 * Copyright (c) 2015, 山东大学 计算机科学与技术专业 学生 * All rights reserved. * 作 者: 高祥 * 完成日期: 2015 年 4 月 12 日 * 版 本 号:017 *任务描述 * 1:给定先序和中序建立二叉树 ; * 2:给定后序和中序建立二叉树 ; *主要函数: * 1.void CreateByPreAndIn(BinaryTree &T,char preorder[],char inorder[],int first,int last);//给定先序和中序建立二叉树 * 2.void CreateByPostAndIn(BinaryTree &T,char postorder[],char inorder[],int first,int last);//给定后序和中序建立二叉树 * 3.void PreOrderTraverse(BinaryTree T);//前序遍历输出二叉树 * 4.void InOrderTraverse(BinaryTree T);//中序遍历输出二叉树 * 5.void PostOrderTraverse(BinaryTree T);//后序遍历输出二叉树 * 6.void print(BinaryTree T);//打印二叉树 */ #include<iostream> #include<cstdlib> using namespace std; typedef struct BTNode//二叉树结点类型 { char data; struct BTNode *leftchild; struct BTNode *rightchild; } BTNode,*BinaryTree; int index; void CreateByPreAndIn(BinaryTree &T,char preorder[],char inorder[],int first,int last);//给定先序和中序建立二叉树 void CreateByPostAndIn(BinaryTree &T,char postorder[],char inorder[],int first,int last);//给定后序和中序建立二叉树 void PreOrderTraverse(BinaryTree T);//前序遍历输出二叉树 void InOrderTraverse(BinaryTree T);//中序遍历输出二叉树 void PostOrderTraverse(BinaryTree T);//后序遍历输出二叉树 void print(BinaryTree T);//打印二叉树 int main() { cout<<"第一组测试数据:\n"; char preorder[]= {'A','B','C','D','E','G','F'}; char inorder[]= {'C','B','E','G','D','F','A'}; char postorder[]= {'C','G','E','F','D','B','A'}; BinaryTree T1; index=0; cout<<"\n由先序和中序建立二叉树:\n"; CreateByPreAndIn(T1,preorder,inorder,0,6); print(T1); BinaryTree T2; index=6; cout<<"\n由后序和中序建立二叉树:\n"; CreateByPostAndIn(T2,postorder,inorder,0,6); print(T2); cout<<"\n\n第二组测试数据:\n"; char preorder2[]= {'A','B','D','E','F','G','C','H','J','I','K'}; char inorder2[]= {'D','B','F','G','E','A','H','J','C','I','K'}; char postorder2[]= {'D','G','F','E','B','J','H','K','I','C','A'}; BinaryTree T3; index=0; cout<<"\n由先序和中序建立二叉树:\n"; CreateByPreAndIn(T3,preorder2,inorder2,0,10); print(T3); BinaryTree T4; index=10; cout<<"\n由后序和中序建立二叉树:\n"; CreateByPostAndIn(T4,postorder2,inorder2,0,10); print(T4); return 0; } void CreateByPreAndIn(BinaryTree &T,char preorder[],char inorder[],int first,int last) //给定先序和中序建立二叉树 { if(first>last) { T=NULL; } if(first==last) { T=(BinaryTree)malloc(sizeof(BTNode)); T->data=preorder[index]; T->leftchild=T->rightchild=NULL; index++; } if(first<last) { int loc; for(loc=first; first<=last; loc++) { if(inorder[loc]==preorder[index]) { break; } } T=(BinaryTree)malloc(sizeof(BTNode)); T->data=preorder[index]; index++; CreateByPreAndIn(T->leftchild,preorder,inorder,first,loc-1); CreateByPreAndIn(T->rightchild,preorder,inorder,loc+1,last); } } void CreateByPostAndIn(BinaryTree &T,char postorder[],char inorder[],int first,int last) //给定后序和中序建立二叉树 { if(first>last) { T=NULL; } if(first==last) { T=(BinaryTree)malloc(sizeof(BTNode)); T->data=postorder[index]; T->leftchild=T->rightchild=NULL; index--; } if(first<last) { int loc; for(loc=first; first<=last; loc++) { if(inorder[loc]==postorder[index]) { break; } } T=(BinaryTree)malloc(sizeof(BTNode)); T->data=postorder[index]; index--; CreateByPostAndIn(T->rightchild,postorder,inorder,loc+1,last); CreateByPostAndIn(T->leftchild,postorder,inorder,first,loc-1); } } void PreOrderTraverse(BinaryTree T)//前序遍历输出二叉树 { if(T) { cout<<T->data<<" "; PreOrderTraverse(T->leftchild); PreOrderTraverse(T->rightchild); } } void InOrderTraverse(BinaryTree T)//中序遍历输出二叉树 { if(T) { InOrderTraverse(T->leftchild); cout<<T->data<<" "; InOrderTraverse(T->rightchild); } } void PostOrderTraverse(BinaryTree T)//后序遍历输出二叉树 { if(T) { PostOrderTraverse(T->leftchild); PostOrderTraverse(T->rightchild); cout<<T->data<<" "; } } void print(BinaryTree T)//打印二叉树 { cout<<"先序遍历为:\n"; PreOrderTraverse(T); cout<<endl; cout<<"中序遍历为:\n"; InOrderTraverse(T); cout<<endl; cout<<"后序遍历为:\n"; PostOrderTraverse(T); cout<<endl; }
相关文章推荐
- 二叉树的建立、前序、中序、后序遍历
- 二叉树的建立和三种遍历(先序、中序和后序)
- 已知二叉树的前序,中序,后序遍历中的两个,求另一个
- 已知二叉树的前序遍历和中序遍历,如何得到它的后序遍历?
- 树的遍历 有后序遍历和中序遍历建立二叉树,并输出层次遍历
- 计算机技术——已知二叉树的前序遍历和中序遍历,如何得到它的后序遍历?
- 根据后序和中序建立二叉树
- 二叉树建立以及先序、中序、后序、层次遍历(JAVA 实现)
- 已知二叉树的前序遍历和中序遍历,如何得到它的后序遍历?
- python实现二叉树的建立以及遍历(递归前序、中序、后序遍历,队栈前序、中序、后序、层次遍历)
- 已知一棵二叉树的后序遍历和中序遍历,写出可以确定这棵二叉树的算法
- 已知二叉树先序、中序(中序、后序)遍历序列,输出后序(先序)遍历序列
- 二叉树的建立和中序、先序、后序遍历
- 二叉树的建立与先序,后序,中序输出
- JS建立二叉树&先序、中序、后序遍历
- 二叉树学习-已知中序、后序,求先序
- 二叉树的相互求解 已知前序中序求后序 已知后序前序求中序 已知前序后序求中序
- 已知先序遍历和中序遍历,求后序遍历 && 求二叉树中节点的最大距离
- LeetCode 106. Construct Binary Tree from Inorder and Postorder Traversal (用中序和后序树遍历来建立二叉树)
- 二叉树的建立以及前序、中序、后序遍历的递归和非递归实现