IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【算法】【树】先序先序、后序序列是否为BST树的先序序列、后序序列(详细解释) -> 正文阅读

[数据结构与算法]【算法】【树】先序先序、后序序列是否为BST树的先序序列、后序序列(详细解释)

题目描述

?给出一个先序/后序序列,判断这个序列是不是某个BST树的先序/后序序列

算法原理

????????核心的思路就是知道当前子树的一个端点(因为是先序/后序序列,所以一个端点肯定是根节点root)和当前子树在序列中的另一个端点(可以记做tail),然后再当前树判断是不是BST树,然后再递归进入当前树的左右子树,再判断左右子树是不是BST树,如果这个序列对应的所有子树都为BST树,说明这个树也为BST树

举例用树

roottail
先序序列865710811
tailroot
后序序列576811108

? ? ? ? 问题1:就到了如何判断一当前树是不是为BST树呢?

? ? ? ? ? ? ? ? ? ?其实只需要判断当前节点作为根节点左子树的所有端点是不是小于当前根节点,右子树的所有节点是不是大于等于当前根节点,只需要满足这棵树的所有节点都是左孩子小于这个节点,右孩子大于等于这个节点就可以了

? ? ? ? 问题2:具体怎么判断是不是当前节点的左子树是不是全小于当前节点,右子树全部大于等于当前节点呢?

? ? ? ? ? ? ? ? ? ??对于先序序列来说,因为是根节点——左子树——右子树,如果满足左子树都小于当前节点,右子树全部大于等于当前节点,就可以划分为根节点——小于根节点——大于等于根节点,因为序列是连续的,所以就可以转变为判断一个序列是不是先小于根节点,再大于等于根节点了,可以设置一个变量p,等于左子树在序列中出现的第一个节点(也就是root+1),先通过while循环找到第一个大于等于根节点的节点,在通过一个while循环判断剩下的值是不是都大于等于根节点,如果最后这个变量p完整的走完了这个序列(也就是说明指向了tail+1),就说明满足左子树小于当前节点,右子树大于等于当前节点。

? ? ? ? ? ? ? ? ? ? 用代码解释就是

	int p=root+1;
    while(p<=tail&&pre[p]<pre[root])	p++;    //先判断小于根结点的
	m=p;    //m是用作记录,用于递归左右子树的判断
	while(p<=tail&&pre[p]>=pre[root])	p++;    //在判断大于等于根结点的
	if(p!=tail+1)	return ;     //如果能走到序列最后就满足
                                 //如果不能走到序列最后就说明不满足,直接返回

? ? ? ? ? ? ? ? ? ??对于后序序列来说,因为最后一个节点是根节点,所以只需要判断从另一个端点tail开始,到root前面那个节点是不是满足条件就可以了

? ? ? ? ? ? ? ? ? ?代码解释

    int p=begin;
    while(postorder[p]<postorder[root]) p++;
    int m=p;
    while(postorder[p]>=postorder[root]&&p<root)    p++;

? ? ? ? ? ? ? ? 对于先序序列,判断的范围是[root+1,tail]

? ? ? ? ? ? ? ? 对于后序序列,判断的范围是[tail,root-1]?

roottail
先序序列865710811
tailroot
后序序列576811108

? ? ? ? ?问题3:知道当前节点判断原理了,如何判断递归进左右子树呢?

? ? ? ? ? ? ? ? ? ? ? 对于一个已经判断完是不是满足的节点后,我们就可以利用一个变量m来记录p代表的第一个大于根节点的节点(也就是第一个while循环后),这个节点m就是右子树的第一个节点,同时也是右子树的根节点,m-1就是左子树的最后一个节点,

? ? ? ? ? ? ? ? ? ? ? ?注意:子树的在先序序列中的第一个节点是root,最后一个节点时tail,

?????????????????????????????????????????????在后序序列中第一个节点时tail,最后一个节点时root

? ? ? ? ? ? 所以对于先序序列来说,左子树的根节点为root+1,左子树在序列中的最后一个位置为m-1

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 右子树的根节点为m,右子树在序列中的最后一个位置为tail? ?

	postOrder(root+1,m-1);	//左子树 
	postOrder(m,tail);		//右子树 

????????????????????对于后序序列来说,左子树的根节点为m-1,左子树的第一个节点为tail????????????????

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 右子树的根节点为root-1,右子树的第一个节点为m

judge(tail,m-1,postorder)    //左子树
judge(m,root-1,postorder)    //右子树

?????????????????????对应序列

rootroot+1m-1mtail
根节点左子树 右子树 
先序序列865710811
tailm-1mroot-1root
 左子树  右子树 根节点
后序序列576811108

? ? ? ? ? ?问题4:递归结束的条件是什么呢?

? ? ? ? ? ? ? ? ? ? ? ? 很显然,当到达叶子结点,只有一个节点的时候肯定是BST树了嘛,当root==tail的时候就说明到达叶子节点了,直接返回就可以了

? ? ? ? ? ? ? ? ? ? ? ? 注意:当先序序列求后序序列,后序序列求先序序列,在叶子结点的时候也要讲叶子结点放入要求的数组中,然后再两次递归结束后也需要将结点放入其中?

核心代码实现

对于先序序列,如果还要求出对应的后序序列,有

void postOrder(int root,int tail){
	if(root>tail)	return ;
	if(root==tail){
		post.push_back(pre[root]);
		return ;
	}
	int i=root+1,j=tail;
	int p=root+1;
	int m;
	while(p<=tail&&pre[p]<pre[root])	p++;
	m=p;
	while(p<=tail&&pre[p]>=pre[root])	p++;
	if(p!=tail+1)	return ; 
	postOrder(root+1,m-1);	//左子树 
	postOrder(m,tail);		//右子树 
	post.push_back(pre[root]);
}

对于后序序列有

bool judge(int begin,int root,vector<int>& postorder){
    if(begin>=root)  return true;
    int p=begin;
    while(postorder[p]<postorder[root]) p++;
    int m=p;
    while(postorder[p]>=postorder[root]&&p<root)    p++;
    return root==p&&judge(begin,m-1,postorder)&&judge(m,root-1,postorder);
}

例题

PAT甲:? ?1043 Is It a Binary Search Tree(前序中序转后序)(两种解法)LeetCode:? ? 剑指 Offer 33. 二叉搜索树的后序遍历序列PAT甲:? ?1043 Is It a Binary Search Tree(前序中序转后序)(两种解法)

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-12-18 16:14:34  更:2021-12-18 16:17:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 16:59:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码