已知两种遍历顺寻求第三种遍历顺序/构造二叉树题型

P1030 [NOIP2001 普及组] 求先序排列 & P1827 [USACO3.4] 美国血统 American Heritage

这次分享一下这两道关于树的基础题的思路(套路)。 

(我终于弄懂这种题目and独立编写ac代码啦!!!走出舒适圈的感觉真爽!!!)

这两道题考察的通过两种遍历方式推导出第三种遍历方式,实质上考察的都是对于树这种数据结构的遍历的理解以及运用。

想了解关于树的遍历的相关知识点可以移步其他巨犇的文章,这里不多赘述。

前序遍历:中左右

中序遍历:左中右

后序遍历:左右中

(这里的左指的是左孩子节点,中指的是父亲节点,右指的是右孩子节点)

注意点:

在后序遍历中,最后一个节点一定是根节点(对于每一颗子树也成立)

在前序遍历中,第一个节点一定是根节点(对于每一颗子树也成立)

我的思路(套路)就是:

首先,根据前序遍历确定根节点,并通过根节点划分出左右子树。

然后,定位两颗子数对应的前序和中序遍历串,递归的进行上述操作。

(可能有点难理解,看看代码吧,拿出笔和草稿纸亲自动手推一下,应该就能理解啦)

P1030 [NOIP2001 普及组] 求先序排列  AC代码:

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
char hou[10];
char zhong[10];
int find(char r_hou)
{
	for(int i=0;i<strlen(hou);i++)
	{
		if(r_hou==zhong[i])
		{
			return i;
		}
	}
}
void dfs(int zhong_l,int zhong_r,int hou_l,int hou_r)
{
	int head=find(hou[hou_r]);
	printf("%c",hou[hou_r]);
	if(head>zhong_l) dfs(zhong_l,head-1,hou_l,hou_r-zhong_r+head-1);
	if(head<zhong_r) dfs(head+1,zhong_r,hou_l+head-zhong_l,hou_r-1);
}
int main()
{
	memset(hou,0,sizeof(hou));
	memset(zhong,0,sizeof(zhong));
	scanf("%s",zhong);
	scanf("%s",hou);
	dfs(0,strlen(zhong)-1,0,strlen(hou)-1);
	return 0;	
}

P1827 [USACO3.4] 美国血统 American Heritage

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
char qian[100];
char zhong[100];
char ans[100];
int index=0;
int find(char a)
{
	for(int i=0;i<(int )strlen(zhong);i++)
	{
		if(a==zhong[i]) return i;
	}
}
void dfs(int qian_l,int qian_r,int zhong_l,int zhong_r)
{
	int m=find(qian[qian_l]);
	if(m>zhong_l) dfs(qian_l+1,qian_r-zhong_r+m+1,zhong_l,m-1);
	if(m<zhong_r) dfs(qian_l+m-zhong_l+1,qian_r,m+1,zhong_r);
	printf("%c",qian[qian_l]);
}
int main()
{
	memset(qian,0,sizeof(qian));
	memset(zhong,0,sizeof(zhong));
	scanf("%s",zhong);
	scanf("%s",qian);
	dfs(0,strlen(qian)-1,0,strlen(zhong)-1);
	return 0;
}

补一道同类型题目,已知中序遍历和后序遍历要求构造二叉树。

leetcode 104:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

int leninorder;
int find(int *inorder,int target)
{
    for(int i=0;i<leninorder;i++)
    {
        if(inorder[i]==target)
        {
            return i;
        }
    }
    return 0;
}
struct TreeNode *dfs(int *inorder,int ileft,int iright,int *postorder,int pleft,int pright)
{
    if(ileft==iright)
    {
        struct TreeNode *p;
        p=(struct TreeNode*)malloc(sizeof(struct TreeNode));
        p->val=inorder[ileft];
        p->right=p->left=NULL;
        return p;
    }
    int mid=find(inorder,postorder[pright]);
    int lenl=mid-ileft;
    int lenr=iright-mid;
    struct TreeNode *root;
    root=(struct TreeNode*)malloc(sizeof(struct TreeNode));
    root->val=inorder[mid];
    if(lenl!=0) root->left=dfs(inorder,ileft,mid-1,postorder,pleft,pright-lenr-1);
    else root->left=NULL;
    if(lenr!=0) root->right=dfs(inorder,mid+1,iright,postorder,pleft+lenl+1,pright-1);
    else root->right=NULL;
    return root;
}

struct TreeNode* buildTree(int* inorder, int inorderSize, int* postorder, int postorderSize)
{
    leninorder=inorderSize;
    struct TreeNode *root;
    root=dfs(inorder,0,inorderSize-1,postorder,0,postorderSize-1);
    return root;
}

感谢!

世界会向那些有目标和远见的人让路!让我们一起加油!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值