判断整数序列是不是二元查找树的后序遍历结果

时间:2022-12-15 11:27:24
题目:输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果。
如果是返回 true,否则返回 false。
例如输入5、7、6、9、11、10、8,由于这一整数序列是如下树的后序遍历结果:
       8
    /       \
  6        10
/    \     /    \
5   7   9    11
因此返回 true。

如果输入7、4、6、5,没有哪棵树的后序遍历的结果是这个序列,因此返回 false。



解答:后续遍历的最后一个点是根结点。有由于是排序树,左子树比根小,右子树比根大。根节点的值必定不是最值。

5、7、6、9、11、10、8,最后一个是8,则可以分为左右子树:左子树:5,7,6 右子树:11,10,8

在左子树中,6是根结点,5<6因此是左子树,7>6因此是右子树,满足排序树的后续遍历。11,10,8同理。

7、4、6、5中,由于7>5,因此7、4、6都是右子树,但是4<5不满足右子树的值大于根结点的值,因此不是排序树。


思路:

1、先根据根结点,把数组分成左右子树,怎么分呢,设一个指针k指向数组第0个元素,当该元素小于根结点的值,指针向后移动,直至指向的元素大于根结点。这样就分为了左右子树。如果没有分成功,即k要么仍指向首元素,要么指向最后一个元素,直接返回false;

2、当分成功后,如果右子树中出现比根结点值小的,不满足排序树条件,返回false;

3、分别对左右子树判断,递归实现,直至剩下一个或两个结点。


程序:

#include <iostream>
using namespace std;

//二叉排序树的后续遍历的最后一个是根,是中间值
int check(int a[],int first,int last)
{
	int i=first;
	int j=last;

	//递归的结束条件:仅剩下两个/一个元素,就不需要遍历了。
	if(j-i<=1)
		return 1;
	else
	{
		int k=i;//k用来指向右子树
		while(k<j && a[k]<=a[j])
		{
			k++;
		}
		cout<<"k i j "<<k<<i<<j<<endl;
		if(k==j || k==i)//根结点不是中间值
			return 0;
		else
		{
			for(int t=k+1;t<j;t++)
			{
				if(a[t]<a[j])//在右子树中没有比根小的值
					return 0;
			}
		
		}
		return check(a,i,k-1);//对左子树判断
		return check(a,k,j-1);//对右子树判断
	
		
	}
}


void main()
{
	//int a[7]={5,7,6,9,11,10,8};
	//int a[]={7,4,6,5};
	int a[]={9,8,7,11,15,12,10};
	int n=sizeof(a)/4;
	cout<<check(a,0,n-1)<<endl;


	system("pause");
}