知识点5:为什么知道先序和后序不等重建二叉树

本文探讨了如何通过先序遍历和后序遍历重建二叉树的复杂性,特别指出在某些情况下(如ABDE和DBEA),仅给出这两个序列可能导致多个可能的树结构。通过代码实例展示了如何利用中序遍历辅助确定根节点和子树结构。
摘要由CSDN通过智能技术生成

我们无法根据树的先序遍历和树的后序遍历得到二叉树的结构,或者说结构是不确定的

单向陷门函数思想

hash函数的功能就是将某个大集合映射到小集合中,例如布隆过滤器或者布谷鸟过滤器。或者我们的一些密码的存储,并不是在数据库中直接放入我们的密码,这样如果数据库被盗或者丢失会造成很严重的损失。那么数据库上存储的密码实际上是我们密码的hash映射或某种加密下的密文。
既然是单向的就说明我们无法从以映射的集合得到原集合。同时这种压缩是有损的。
因此一棵树也可以看做是一个哈希映射。我们将含有n个节点的二叉树映射成为串长为n的一个字符串。那么你可能说,这不是没有损失节点吗?
千万别忘了,当二叉树用链表表示的时候,含有n个节点的二叉链表有n+1个空链域,就是二叉树中叶子节点指向的空指针。
因此当根据某个序列还原二叉树就会有很大的不确定性。
但是有个特殊的例子:只给出先序遍历和后序遍历无法还原出确定性的二叉树来

根据序列分析

我们可以看到当给定中序遍历的时候和任意后序或前序遍历时,我们可以很容易的把根节点找到。
比如分别有前序遍历和中序遍历:12463578和26417583
我们可以很容易的就可以根据先序遍历确定1为根节点,接着在中序遍历中找到1。1左边的就是左子树,右边的是右子树。
递归上述过程可以很容易就得出来完整且唯一的二叉树
———————————————————————————————————————————————————————————————————————————————————————————————————
但是如果我给定一个先序遍历序列和后序遍历序列:ABDE和DBEA
我们只能知道根节点是A,而对剩下的结构无法肯定。
因为我们观察后序遍历可以看到D是第一个被遍历的,这说明D必然为叶子节点。所以E肯定是A的有孩子
但是对于B和D我们无法肯定,我们唯一能确定的就是B是D的父亲节点
所以对于上述两个序列有两种可能:
在这里插入图片描述
————————————————————————————————————————————————————————————

代码实现

定义树的结构.h文件

#ifndef CONSTRUCT_H_
#define CONSTRUCT_H_
struct BTree
{	
	int val;
	BTree *left;
	BTree *right;
	BTree(int x):val(x),left(nullptr),right(nullptr){}
};
#endif // CONSTRUCT_H_

主体结构

#include<iostream>
#include"define_tree.h"
#include<vector>
using namespace std;
//返回根节点在中序遍历中的位置
int get_index(int *obj,int a,int length) {
	for (int i = 0;i < length- 1;i++) {
		if (obj[i]==a) {
			return i;
		}
	}
}
//根据前序和中序还原二叉树
BTree *build_tree_bypre(int *pre,int *mid,int length) {
	//递归终止条件
	if (length<=0) {
		return 0;
	}
	BTree *root = new BTree(pre[0]);
	int index = get_index(mid,root->val,length);
	root->left=build_tree_bypre(pre+1,mid,index);
	root->right = build_tree_bypre(pre+index+1,mid+index+1,length-index-1);
	return root;
}
//根据中序和后序还原二叉树
BTree *build_tree_bybac(int *bac, int *mid,int length) {
	//递归终止条件
	if (length <= 0) {
		return 0;
	}
	BTree *root = new BTree(bac[length-1]);
	int index = get_index(mid,root->val,length);
	root->left = build_tree_bybac(bac,mid,index);
	root->right = build_tree_bybac(bac+index,mid+index+1,length-index-1);
	return root;
}

//中序遍历二叉树
void mid_order(BTree *root) {
	if (root==nullptr) {
		return ;
	}
	mid_order(root->left);
	cout << root->val << " ";
	mid_order(root->right);
}
int main() {
	int  pre[] = {4,1,3,2,6,5,7};
	int  mid[] = {1,2,3,4,5,6,7};
	int  back[] = {2,3,1,5,7,6,4};
	int length = 7;
	mid_order(build_tree_bybac(back, mid, length));
	cout << endl;
	mid_order(build_tree_bypre(pre, mid, length));
	system("pause");
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值