题目描述:判断整数序列是不是二元查找树的后序遍历结果
输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果。
如果是返回true,否则返回false。
例如输入5、7、6、9、11、10、8,由于这一整数序列是如下树的后序遍历结果:
8
/ \
6 10
/ \ / \
5 7 9 11 因此返回true。
如果输入7、4、6、5,没有哪棵树的后序遍历的结果是这个序列,因此返回false。
思路分析:
查找二叉树的特点就是左子树中的节点一定比根节点小,右子树中的节点一定比根节点大。OK,那用根节点就可以将数组分成两部分。步骤如下:
*从前往后遍历,找到第一个大于根节点的数。
*从这个数往后,判断是不是所有的在根节点以前的数都大于根节点,如果不是,那就不可能是查找二叉树的后序遍历结果。
*如果前面两个步骤都没问题,那就分别再判断左子树和右子树是否合法。
题目扩展:其实这道题考的就是树的重建。另一种方式就是利用树的前序遍历和中序遍历,重建二叉树,最后输出树的后序遍历。具体做法参考博客: 重建二叉树和 重建二叉树第二季。
1、首先给出递归的解法,如果是递归的话,找到左子树和右子树之后,就改变参数就可以了。参考代码如下:
输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果。
如果是返回true,否则返回false。
例如输入5、7、6、9、11、10、8,由于这一整数序列是如下树的后序遍历结果:
8
/ \
6 10
/ \ / \
5 7 9 11 因此返回true。
如果输入7、4、6、5,没有哪棵树的后序遍历的结果是这个序列,因此返回false。
思路分析:
查找二叉树的特点就是左子树中的节点一定比根节点小,右子树中的节点一定比根节点大。OK,那用根节点就可以将数组分成两部分。步骤如下:
*从前往后遍历,找到第一个大于根节点的数。
*从这个数往后,判断是不是所有的在根节点以前的数都大于根节点,如果不是,那就不可能是查找二叉树的后序遍历结果。
*如果前面两个步骤都没问题,那就分别再判断左子树和右子树是否合法。
题目扩展:其实这道题考的就是树的重建。另一种方式就是利用树的前序遍历和中序遍历,重建二叉树,最后输出树的后序遍历。具体做法参考博客: 重建二叉树和 重建二叉树第二季。
1、首先给出递归的解法,如果是递归的话,找到左子树和右子树之后,就改变参数就可以了。参考代码如下:
//给出递归的解法
bool PostOrderToBst(int *arr, int nLen)
{
if(!arr || nLen < 1)
return false;
int i;
for(i = 0; i < nLen - 1; ++i)
{
if(arr[i] > arr[nLen - 1])
break;
}
for(int j = i + 1; j < nLen - 1; ++j)
{
if(arr[j] < arr[nLen - 1])
return false;
}
bool Left = true;
bool Right = true;
if(i > 1)//i为左子树节点的个数,小于2可以忽略
Left = PostOrderToBst(arr, i);
if(nLen - i > 1)//nLen-i为右子树节点的个数,小于2可以忽略
Right = PostOrderToBst(arr, nLen - i);
return Left && Right;
}
2、如果用非递归来做,那么就用一个辅助栈来保存中间的结果,然后解决的思路不变,参考代码如下:
//利用辅助栈完成判断
const int N = 30;
bool JudgePostOrder(int *arr, int nLen)
{
if(!arr || nLen < 1)
return false;
int stack[N][2];
int top = 0;
int Begin, End,i,j;
stack[0][0] = 0;
stack[0][1] = nLen - 1;
while(top > -1)
{
Begin = stack[top][0];
End = stack[top][1];
--top;
for(i = Begin; i < End; ++i)
{
if(arr[i] > arr[End])
break;
}
for(j = i + 1; j < End; ++j)
{
if(arr[j] < arr[End])
return false;
}
//i - Begin为左子树节点的个数,小于2可以忽略
if(i - Begin > 1)
{
stack[++top][0] = Begin;
stack[top][1] = i - 1;
}
//End - Begin + 1 - i为右子树节点的个数,小于2可以忽略
if(End - Begin > i)
{
stack[++top][0] = i;
stack[top][1] = End - 1;
}
}//end while
return true;
}
3、最后给出main函数的调用方法,不需要的可以直接pass。
#include<stdio.h>
int main()
{
int arr[N];
int n,i;
bool IsPostOrder;
while(scanf("%d", &n) != EOF)
{
for(i = 0; i < n; ++i)
scanf("%d", &arr[i]);
IsPostOrder = PostOrderToBst(arr, n);
if(IsPostOrder)
printf("递归:Yes\n");
else
printf("递归:No\n");
IsPostOrder = JudgePostOrder(arr, n);
if(IsPostOrder)
printf("非递归:Yse\n");
else
printf("非递归:No\n");
}
}