1. 程式人生 > >BST(二叉搜尋/排序樹)類模板的實現

BST(二叉搜尋/排序樹)類模板的實現

BST樹的遞迴定義:
(1)BST樹是一棵空樹。
(2)BST樹由根節點、左子樹和右子樹。左子樹和右子樹分別都是一棵BST樹。

由於二叉樹的遞迴定義,使得在二叉樹中許多操作中可以以遞迴的方式書寫操作,程式碼更加淺顯易懂。

重點條件:左子樹中的所有節點的資料域都小於或等於根節點的資料域,而右子樹中的所有節點的資料域都大於等於根節點的資料域。根據這個特點,BST樹的中序遍歷是一個由小到大的順序序列。

BST樹刪除任意節點操作相對較難,這裡分析一下。由於BST樹的特點,對於任意一棵BST樹均滿足根節點的資料大於等於左子樹任意節點的資料域,同時滿足根節點的資料域小於等於右子樹任意節點的資料域。根據這個特點,BST樹中最左邊的節點的資料域一定是BST的最小值,而BST樹中最右邊的節點的資料域一定是BST的最大值。而刪除任意一個節點可以歸結為以下三類:



(1)一個節點有右子樹,而沒有左子樹。
(2)一個節點有左子樹,而沒有右子樹。
(3)一個節點既有左子樹又有右子樹。(最難)
(4)一個節點為葉子節點。(可以歸結到(1)和(2)兩種情況當中)

一個節點有右子樹,而沒有左子樹
一個節點有左子樹,而沒有右子樹
對於一個既有左子樹又有右子樹的節點來講,在刪除該節點之後,為了繼續維持BST樹的性質,選擇一個合適的節點作為新樹的根節點是非常有必要的。

如何選取?根據BST的定義,很容易觀察到,當前節點右子樹中所有節點均大於當前節點。但是在右子樹中的最小值一定小於右子樹其他節點,因此我們可以選取這個最小值所在的節點作為新BST的根,因為它繼續滿足BST對於任意節點,其資料大於左子樹任意節點的資料域但同時小於右子樹中任意節點的資料域的性質。此外,很對稱是當前右子中的最大值所在節點也可以作為新樹的根,它也繼續滿足BST樹的性質。
在這裡插入圖片描述

template<typename T>
class BST{
private:
	//節點類
	struct Node{
		T value;
		Node *left,*right;//指向左右孩子的指標
		Node(T value){
			this->value = value;
			this->right = this->left = NULL;
		}
		//用另外一個節點的資訊構造節點
		Node(Node* node){
			this->value = value;
			this->left = node->left;
			this->right = node->right;
		}
	};
	/*插入資料域為value的節點,插入之後整個BST任然滿足BST的定義
	返回值為插入資料域為value節點後,BST樹的根節點。*/
	Node* insert(Node* node,T value){
		//空樹和非空樹兩種情況
		if(node == NULL){
			//空樹	
			size ++;//維護樹中節點的個數
			return new Node(value);
		}
		else{
			//非空樹
			//樹中已有資料域為value的節點,更新該節點
			if(value == node->value){
				node->value = value;
				return node;
			}
			else if(value < node->value){
				//value比當前節點的資料域小,根據二叉樹的定義,應插入在其左子樹中
				node->left = insert(node->left,value);
				return node;
			}
			else{
				node->right = insert(node->right,value);
				return node;
			}
		}
	}
	//獲取BST樹中資料域最大值所在的節點
	Node* maxValue(Node* node){
		//如果當前節點的右子樹為空樹,當前節點的資料域即為BST樹的最大值
		if(node->right == NULL){
			return node;
		}
		return maxValue(node->right);
	}
	//獲取BST樹中資料與最小值所在的節點
	Node* minValue(Node* node){
		//如果當前節點的左子樹為空樹,則當前節點的資料域即為整個BST樹的最小值
		if(node->left == NULL){
			return node;
		}
		return minValue(node->left);
	}		

	//返回刪除最小值後BST樹的根
	Node* deleteMin(Node* node){
		/*如果當前節點的左子樹為空樹,即當前節點的資料域為BST樹的最小值。
		只需要將當前節點的右子樹替代當前節點即可*/
		if(node->left == NULL){
			//儲存當前節點的右子樹
			Node* rightTree = node->right;
			delete node;
			size --;//維護size的定義
			return rightTree;
		}
		else{
			//在當前節點右子樹樹中刪除
			node->left = deleteMin(node->left);
			return node;    
		}
	}
	Node* deleteMax(Node* node){
		if(node->right == NULL){
			Node* leftTree = node->left;
			delete node;
			size --;
			return leftTree;
		}
		else{
			node->right = deleteMax(node->right);
			return node;
		}
	}
	Node* remove(Node* node,T value){
		if(node == NULL){
			return node;
		}
		else{
			if(value < node->value){
				node->left = remove(node->left,value);
				return node;
			}
			else if(value > node->value){
				node->right = remove(node->right,value);
				return node;
			}	
			else{
				if(node->right == NULL){
					Node* leftTree = node->left;
					delete node;
					size --;
					return leftTree;
				}
				else if(node->left == NULL){
					Node* rightTree = node->right;
					delete node;
					size --;
					return rightTree;
				}
				else{
					Node* deleteNode = node;
					Node* newTree = new Node(minValue(node->right));
					size ++;
					newTree->right = deleteMin(node->right);
					newTree->left =  node->left;
					delete node;
					size --;
					return newTree;
				}
			}
		}
	}
	//中序遍歷
	void inorder(Node* node){
		if(node!=NULL){
			inorder(node->left);
			cout<<node->value<<" ";
			inorder(node->right);
		}
	}
	void destroy(Node* node){
		if(node!=NULL){
			destroy(node->left);
			destroy(node->right);
			delete node;
			size --;
		}
	}
	Node* root;//BST樹的根節點
	int size;//BST樹總結點個數
public:
	BST(){
		root = NULL;
		size = 0;
	}
	~BST(){
		destroy(root);//釋放以root為根的二叉樹節點在heap中的資源
	}
	//獲取當前BST樹節點個數
	int getSize(){return size;}
	//判斷一棵BST是否為空樹
	bool isEmpty(){return size==0;}
	void insert(T value){
		//呼叫私有的方法,使用者只能使用此介面,實現插入操作
		root = insert(root,value);
	}
	//獲取BST樹中的最大值
	T maxValue(){
		if(root!=NULL){
			Node* maxNode = maxValue(root);
			return maxNode->value;
		}
	}
	//獲取BST樹中的最小值
	T minValue(){
		if(root!=NULL){
			Node* minNode = minValue(root);
			return minNode->value;
		}
	}
	//刪除BST樹最小值所在的節點
	void deleteMax(){
		if(root!=NULL){
			root = deleteMax(root);
		}
	}
	//刪除BST樹最大值所在的節點
	void deleteMin(){
		if(root!=NULL){
			root = deleteMin(root);
		}
	}
	//刪除BST樹中資料域為value的節點,即刪除二叉樹中的任意節點
	void remove(T value){
		if(root!=NULL){
			root = remove(root,value);
		}
	}
	void inorder(){
		inorder(root);
	}
};

測試:

#include<iostream>
using namespace std;
int main(void){
	int arr[] = {9,5,3,4,1,7,2,8,0};
	int n = sizeof(arr)/sizeof(int);
	BST<int> bst;
	for(int i = 0;i<n;++i){
		bst.insert(arr[i]);
	}
	bst.inorder();
	cout<<"max:"<<bst.maxValue()<<endl;
	cout<<"min:"<<bst.minValue()<<endl;
	cout<<"刪除的節點是:value==4"<<endl;
	bst.remove(4);
	bst.inorder();
	return 0;
}

執行結果:

在這裡插入圖片描述