二叉树的重构

本文探讨了如何根据二叉树的前序、中序遍历重构二叉树,以及如何判断一个序列是否是有序二叉树的后序遍历结果。通过递归方法解决这些问题,并提供了相关解题思路和代码实现。
摘要由CSDN通过智能技术生成

二叉树的重构

引言:本篇博客想和大家讨论一下有关二叉树的遍历问题,小编在最近学习二叉树时总被递归遍历绕晕,希望这篇“血泪”酿成的心得能帮助到大家

结点结构和所用到的函数声明

#define TYPE int

typedef struct TreeNode       //二叉树结点结构
{
	TYPE data;                //二叉树存储内容
	struct TreeNode* left;    //二叉树的左指针 → 指向左孩子 
	struct TreeNode* right;   //二叉树的右指针 → 指向右孩子
}TreeNode;

TreeNode* create_node(TYPE data);  //创建一个二叉树结点,形参为结点的内容

本篇博客的题目来自牛客网→题库→在线编程→ 剑指offer

问题1:现在有一个树的前序遍历和中序遍历,重新构建二叉树
解题思路:


我们均以该树讲解

前序遍历结果:(4,2,1,3,5)
中序遍历结果:(1,2,3,4,5)
3种遍历的访问顺序:前序遍历→根左右 、 中序遍历→左根右 、 后序遍历→左右根


判断1:前序遍历中排头结点是一颗树的根结点,对其子树同样适用
证明1:上述树中,4为整颗树的根结点,2为左子树的根结点,5为右子树的根结点,以此类推

判断2:中序遍历中在根结点左边的为其左子树结点,根结点右边的为其右子树结点,对这颗树的子树同样适用
证明2:上述树中,(1,2,3)是根结点4的左子树,(5)是根结点4的右子树,以此类推


通过上述判断,我们可以将一颗二叉树通过前序遍历确定根结点,中序遍历确定该根结点的左右孩子,再从左右子树中找其根结点与其对应的左右孩子……
讲到这我们可以自然而然的想到使用递归解题,下附代码

实现代码:
TreeNode* reconstruct_tree(TYPE* pre, TYPE* in, size_t size) 
//pre为前序序列数组,in为中序序列数组,size为数组的大小
//默认调用者输入大小相等的两个数组
{
	if(0 >= size) return NULL;
    TreeNode* root = create_node(pre[0]);
	int len = 0;
	for(; len<size; ++len)
	{
        if(in[len] == pre[0])	break;
	}
	//此时将数组下标作为长度是因为此时并不包括这个root结点
    root->left = reconstruct_tree(pre+1,in,len);
    root->right = reconstruct_tree(pre+1+len,in+len+1,size-1-len);
	return root;
}

问题2:判断一个序列是否是有序二叉树的后序遍历结果(bool 类型)
解题思路:

有序二叉树:结点的左孩子内容小于父结点内容,右孩子内容大于父结点内容


当理解了问题1的思路后 ,我们首先想到的就是后续遍历 → 左右根
在这里插入图片描述

后序遍历结果:(1,3,2,5,4)


判断1:后续遍历将一颗树的顺序分成左子树,右子树,根
证明1:(1,3,2)为根结点4的左子树成员,(5)为根结点4的右子树成员,对其子树也适用

判断2:在有序二叉树中,左子树的成员内容均小于其根结点内容,右子树则反之
证明2:(1,3,2)均小于4,(5)大于4,对其子树也适用


通过上述分析,我们的目标便成了将一个后续序列逐级分成三个部分(左,右,根)

实现代码:
bool helper_BST(TYPE* arr, int head, int tail)
//head为数组的头,tail为数组的尾,通过修改改值来得到对应子树的序列
{
	if(head >= tail)
        return true;
	int pivot = head;
	while(arr[pivot] < arr[tail])
		pivot++;

    for(int j = pivot;j<tail;++j)  //防止在右子树中有值小于根结点的值
        if(arr[j]<arr[tail])
            return false;

    bool flag = helper_BST(arr,head,pivot-1);  
//左子树不满足要求则无需对右子树进行判断
    if(flag) flag = helper_BST(arr,pivot,tail-1);

    return flag;
}


bool VerifySquenceOfBST(TYPE* sequence, int size)
{
	if(0 >= size) return false;
	return helper_BST(sequence,0,size-1);
}

总结

本文主要简单介绍了小编对二叉树前序、中序、后续遍历的看法,在代码的精简性上仍有不足,望大佬们海涵,若有表述不当,可优化代码部分请及时指出。小编衷心希望能对初学二叉树的大家带来一点解题的灵感。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值