1. 程式人生 > >C++ 判斷一顆樹是否是BST(二叉排序樹)

C++ 判斷一顆樹是否是BST(二叉排序樹)

方法一:使用中序遍歷

因為二叉排序樹的中序遍歷結果是遞增的,所以可以通過中序遍歷儲存結果,再判斷是否為遞增的陣列。
1) 對樹進行中序遍歷,將結果儲存在b[]陣列中。
2) 檢測b[]陣列中元素是否為升序排列。如果是,則這棵樹為BST.
時間複雜度: O(n)

程式碼如下:

#include<iostream>
#include<algorithm>
using namespace std;
 
typedef struct BinaryTreeNode{
	int value;
	BinaryTreeNode *m_pLeft;
	BinaryTreeNode *m_pRight;
}BTNode;

int max_height = -1;
 
void addBTNode(BTNode *&myBT,int val);//新增節點 
void createBT(BTNode *&BT,int arr[],int n);//建立二叉排序樹,通過*&來改變指標的值

void midorder_showBT(BTNode *myBT);//中序遍歷列印,如果是二叉排序樹,列印結果與單調遞增陣列一樣

int b[100];
int idx = 0;
void is_BST(BTNode *myBT);//判斷是否是二叉排序樹 
 
int main(){
	
	BTNode *myBT = nullptr;
	
	int arr[10] = {314,426,12,78,143,8,21,14,9,314};
	createBT(myBT,arr,10);
	
	midorder_showBT(myBT);
	cout<<endl;
	
	is_BST(myBT);
	bool isBT = true;
	if(idx == 1 || idx == 0)
		cout<<"是BST"<<endl;
	else{
		for(int i=0;i < idx - 1;i++){
			if(b[i] >= b[i+1]){
				isBT = false;
				break;
			}
		} 
		if(isBT)
			cout<<"是BST"<<endl;
		else
			cout<<"不是BST"<<endl;	
	} 
	return 0;
}

void is_BST(BTNode *myBT){
	if(myBT == nullptr )
		return ;
	is_BST(myBT->m_pLeft);
	b[idx++] = myBT->value;
	is_BST(myBT->m_pRight);
}

void createBT(BTNode *&BT,int arr[],int n){
	BT = nullptr;
	for(int i=0;i<n;i++)
		addBTNode(BT,arr[i]);	
}


void addBTNode(BTNode *&myBT,int val){
	if(myBT == nullptr){
		myBT = new BinaryTreeNode();
		myBT->value = val;
		myBT->m_pLeft = nullptr;
		myBT->m_pRight = nullptr;
		return;	
	}
		
	if(val == myBT->value){
		return;
	}
	else if(val < myBT->value){
		addBTNode(myBT->m_pLeft,val);
	}
	else{
		addBTNode(myBT->m_pRight,val);
	}			
}

 
void midorder_showBT(BTNode *myBT){//中序遍歷列印 {
	if(myBT == nullptr )
		return;
	
	midorder_showBT(myBT->m_pLeft);
	cout<<myBT->value<<" ";
	midorder_showBT(myBT->m_pRight);
} 

方法二:限定二叉樹中節點值的範圍,優化演算法每個節點只需訪問一次

限定了子樹中節點值的範圍,從而每個節點只需訪問一次。節點值的初始範圍可限定為INT_MIN以及INT_MAX。
//判斷是否為BST
bool is_BT(BTNode *myBT,int min,int max){
if(myBT == nullptr || min > max)
return false;
return is_BT_Core(myBT,min,max);
}
//如果是一顆二叉查詢樹,且值範圍在[min,max],則返回true

bool is_BT_Core(BTNode *myBT,int min,int max);

程式碼實現如下:

#include<iostream>
#include<algorithm>
using namespace std;
 
typedef struct BinaryTreeNode{
int value;
BinaryTreeNode *m_pLeft;
BinaryTreeNode *m_pRight;
}BTNode;


int max_height = -1;
 
void addBTNode(BTNode *&myBT,int val);//新增節點 
void createBT(BTNode *&BT,int arr[],int n);//建立二叉排序樹,通過*&來改變指標的值
void midorder_showBT(BTNode *myBT);//中序遍歷列印,如果是二叉排序樹,列印結果與單調遞增陣列一樣


bool is_BT(BTNode *myBT,int min,int max);//判斷是否是BST(二叉排序樹) 
bool is_BT_Core(BTNode *myBT,int min,int max);//判斷是否是BST(二叉排序樹) 核心函式


int min_val = 1,max_val = 1000; 
 
int main(){

BTNode *myBT = nullptr;

int arr[] = {314,426,12,78,143,8,21,14,9,314};
createBT(myBT,arr,sizeof(arr)/sizeof(arr[0]));

cout<<"中序遍歷結果:"<<endl; 
midorder_showBT(myBT);
cout<<endl;

if(is_BT(myBT,min_val,max_val)){
cout<<"此二叉樹是BST"<<endl; 
}else
cout<<"此二叉樹不是BST"<<endl; 

return 0;
}


bool is_BT(BTNode *myBT,int min,int max){
if(myBT == nullptr || min > max)
return false;//空子樹返回false 
return is_BT_Core(myBT,min,max);
}


bool is_BT_Core(BTNode *myBT,int min,int max){
if(myBT == nullptr)//空結點時返回true結束 
return true;

//如果節點值違反了最大/最小約束條件,則不是BST
if( (myBT->value < min) || (myBT->value > max) )
return false;

return is_BT_Core(myBT->m_pLeft,min,myBT->value - 1) 
       && is_BT_Core(myBT->m_pRight,myBT->value + 1,max);
}




void createBT(BTNode *&BT,int arr[],int n){
BT = nullptr;
for(int i=0;i<n;i++)
addBTNode(BT,arr[i]);
}




void addBTNode(BTNode *&myBT,int val){
if(myBT == nullptr){
myBT = new BinaryTreeNode();
myBT->value = val;
myBT->m_pLeft = nullptr;
myBT->m_pRight = nullptr;
return;
}

if(val == myBT->value){
return;
}
else if(val < myBT->value){
addBTNode(myBT->m_pLeft,val);
}
else{
addBTNode(myBT->m_pRight,val);
}
}

void midorder_showBT(BTNode *myBT){//中序遍歷列印 {
if(myBT == nullptr )
return;

midorder_showBT(myBT->m_pLeft);
cout<<myBT->value<<" ";
midorder_showBT(myBT->m_pRight);
}

執行結果如下: