二叉树: 如果每个节点的儿子结点不多于两个,称这棵树为二叉树;
每个父节点的两个儿子节点在区间的时候可以分别称为该父节点的左儿子和右儿子,以左儿子为根的子树又被称为左子树,以右儿子为根的子树又被称为右子树。
如果一棵二叉树的任意节点或者是树叶,或者恰有两棵非空子树,则此二叉树被称为满二叉树。
如果一棵二叉树最多只有最下面的两层节点度数小于2,并且最下面一层的节点都集中在该层的最左边的连续位置上,则此二叉树称为完全二叉树。
对于深度优先搜索,二叉树定义了3种遍历形式,分别是先序遍历,中序遍历,后序遍历。这三种遍历形式的思想同为深度优先,但是遍历的顺序不同。
先序遍历: (根,左,右)
即①:访问根结点
②:先序遍历左子树;
③:先序遍历右子树;
中序遍历: (左,根,右)
即①:中序遍历左子树;
②:访问根结点;
③:中序遍历右子树;
后序遍历: (左,右,根)
即①: 后序遍历左子树;
②: 后序遍历右子树;
③: 访问根结点;
对于二叉树来说,三种遍历都很重要;
下面举出一些不同顺序遍历的特性:
前序遍历的第一个节点一定是根;
后序遍历的最后一个节点一定是根;
中序遍历中根前面的点一定属于左子树,根后面的点一定属于右子树。
那么对于一题由一棵二叉树的前序遍历和中序遍历求后序遍历;(HDU1710);
首先我们确定根节点,然后对于中序遍历,根节点左子树和右子树中间,我们又能知道左子树和右子树的个数,然后再到前序遍历,前序遍历又默认一棵树的左子树在右子树的前面,所以一棵二叉树就被分成了根节点,左子树,右子树,一直递归,即可得到二叉树的构造。
最后求一个后序遍历只要写一个后序遍历的深度优先搜索就好了。
简要的一些图示说明;(可以拉到外面去看,比较清楚)
AC代码:
#include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #include <queue> using namespace std; const int INF=0x3f3f3f3f; const int N=1e3+10; struct asd{ asd* L; asd* R; int w; }; asd *root; int pre[N]; int in[N]; asd* Creat(int *pre,int *in,int n) { asd* tmp; for(int i=0;i<n;i++) { if(pre[0]==in[i]) { tmp=(asd *)malloc(sizeof(asd)); tmp->w=in[i]; tmp->L=Creat(pre+1,in,i); tmp->R=Creat(pre+i+1,in+i+1,n-(i+1)); return tmp; } } return NULL; } void postorder(asd *p) { if(p!=NULL) { postorder(p->L); postorder(p->R); if(p==root) printf("%d ",p->w); else printf("%d ",p->w); } } int main() { int n; while(~scanf("%d",&n)) { for(int i=0;i<n;i++) scanf("%d",&pre[i]); for(int i=0;i<n;i++) scanf("%d",&in[i]); root=Creat(pre,in,n); asd *p=root; postorder(p); } return 0; }