hihocoder#1049之二叉树遍历问题

已知任意两种遍历求另一种遍历(注:已知前序和后序遍历求出的中序遍历可能不唯一)


PreOrder:         GDAFEMHZ

InOrder:            ADEFGHMZ

PostOrder:       AEFDHZMG

 

已知一棵树的前序遍历是”GDAFEMHZ”,中序遍历是”ADEFGHMZ”,后续遍历?

 

第一步,前序遍历的第一节点G就是root。


第二步,继续观察前序遍历GDAFEMHZ,除了知道G是root,剩下的节点必然是root的左右子树之外,

没法找到更多信息了。


第三步,那就观察中序遍历ADEFGHMZ。其中root节点G左侧的ADEF必然是root的左子树,

G右侧的HMZ必然是root的右子树。


第四步,观察左子树ADEF,左子树的中的根节点必然是大树的root的leftchild。在前序遍历中,

大树的root的leftchild位于root之后,所以左子树的根节点为D。


第五步,同样的道理,root的右子树节点HMZ中的根节点也可以通过前序遍历求得。在前序遍历中,

一定是先把root和root的所有左子树节点遍历完之后才会遍历右子树,并且遍历的右子树的第一个

节点就是右子树的根节点。

如何知道哪里是前序遍历中的左子树和右子树的分界线呢?通过中序遍历去数节点的个数。

在上一次中序遍历中,root左侧是A、D、E、F,所以有4个节点位于root左侧。那么在前序遍历中,

必然是第1个是G,第2到第5个由A、D、E、F过程,第6个就是root的右子树的根节点了,是M。

 

第六步,观察发现,上面的过程是递归的。先找到当前树的根节点,然后划分为左子树,右子树,

然后进入左子树重复上面的过程,然后进入右子树重复上面的过程。最后就可以还原一棵树了。


第七步,其实,如果仅仅要求写后续遍历,甚至不要专门占用空间保存还原后的树。

仅需要把第六步的递归的过程改动为如下:


1 确定根,确定左子树,确定右子树。

2 在左子树中递归。

3 在右子树中递归。

4 打印当前根。


另外,已知前后求中还有已知中后求前与上述分析类似,在此不赘述。


#if(1)
//已知前中求后
#include
   
   
    
    
#include
    
    
     
     
#include
     
     
      
      
using namespace std;

void post(char * preorder, char * inorder, int length)
{
	if(!length)
		return;
	int i = 0;
	for(; i < length; i++)
	{
		if(inorder[i] == preorder[0])
			break;
	}
	post(preorder + 1, inorder, i);
	post(preorder + 1 + i, inorder + 1 + i, length - i - 1);
	cout<
      
      
       
       
#include
       
       
         #include 
        
          using namespace std; void in(char * preorder, char * postorder, int length) { if(!length) return; int i = 0; char t = postorder[length - 2]; for(; i < length; i++) { if(t == preorder[i]) break; } in(preorder + 1, postorder, i - 1); cout< 
         
           #include 
          
            #include 
           
             using namespace std; void pre(char * inorder, char * postorder, int length) { if(!length) return; int i = 0; char t = postorder[length - 1]; for(; i < length; i++) { if(inorder[i] == t) break; } cout< 
             
            
           
          
         
       
      
      
     
     
    
    
   
   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值