1. 程式人生 > >PAT-L2-004. 這是二叉搜尋樹嗎?(資料結構)

PAT-L2-004. 這是二叉搜尋樹嗎?(資料結構)

一棵二叉搜尋樹可被遞迴地定義為具有下列性質的二叉樹:對於任一結點,

  • 其左子樹中所有結點的鍵值小於該結點的鍵值;
  • 其右子樹中所有結點的鍵值大於等於該結點的鍵值;
  • 其左右子樹都是二叉搜尋樹。

所謂二叉搜尋樹的“映象”,即將所有結點的左右子樹對換位置後所得到的樹。

給定一個整數鍵值序列,現請你編寫程式,判斷這是否是對一棵二叉搜尋樹或其映象進行前序遍歷的結果。

輸入格式:

輸入的第一行給出正整數N(<=1000)。隨後一行給出N個整數鍵值,其間以空格分隔。

輸出格式:

如果輸入序列是對一棵二叉搜尋樹或其映象進行前序遍歷的結果,則首先在一行中輸出“YES”,然後在下一行輸出該樹後序遍歷的結果。數字間有1個空格,一行的首尾不得有多餘空格。若答案是否,則輸出“NO”。

輸入樣例1:
7
8 6 5 7 10 8 11
輸出樣例1:
YES
5 7 6 8 11 10 8
輸入樣例2:
7
8 10 11 8 6 7 5
輸出樣例2:
YES
11 8 10 7 5 6 8
輸入樣例3:
7
8 6 8 5 10 9 11
輸出樣例3:

NO

分析: 因為是判斷是否為二叉搜尋樹,所以可以利用它的特性,結點左邊的都比結點小,結點右邊的都不小於結點

然後給出的是先序遍歷(根左右) 所以要找哪些是左子樹,哪些是右子樹,只需要從前往後比較找出第一個大於結點的,從後往前找出第一個小於根結點的

(如果這兩個的距離大於1 說明不是二叉搜尋樹) 遞迴下去就可以了~

程式碼:

#include<bits/stdc++.h>
using namespace std;
vector<int>v;
int value[2000];
void vjudge(int L,int R,int flag)
{
	int l=L+1,r=R;
	if(L>R) return;
	if(!flag)
	{
		while(l<=R&&value[l]<value[L]) l++;
		while(r>L&&value[r]>=value[L]) r--;
	}
	else
	{
		while(l<=R&&value[l]>=value[L]) l++;
		while(r>L&&value[r]<value[L]) r--;
	}
	if(l-r!=1) return;
	vjudge(L+1,r,flag);
	vjudge(l,R,flag);
	v.push_back(value[L]);
}
int main()
{
	int n;
	scanf("%d",&n);
	for(int i=0;i<n;i++)
	scanf("%d",&value[i]);
	vjudge(0,n-1,0);
	if(v.size()==0)
	{
		vjudge(0,n-1,1);
	}
	if(v.size()==n)
	{
		printf("YES\n");
		for(int i=0;i<n;i++)
		printf("%d%c",v[i],i==n-1?'\n':' ');
	}
	else
		printf("NO\n");
}