BST(二叉搜索/排序树)类模板的实现

2022-02-24 18:49:25 浏览数 (1)

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树的性质。

代码语言:javascript复制
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);
	}
};

测试:

代码语言:javascript复制
#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;
}

执行结果:

0 人点赞