【数据结构】二叉搜索树

二叉搜索树的性质:
  1. 每个节点都有一个作为搜索依据的关键码(key),所有节点的关键码互不相同。
  2. 左子树上所有节点的关键码(key)都小于根节点的关键码(key)。
  3. 右子树上所有节点的关键码(key)都大于根节点的关键码(key)。
  4. 左右子树都是二叉搜索树。
    //BSTree.h
    
    #pragma once 
    
    template<class K,class V>
    struct BSTreeNode
    {
    	BSTreeNode(const K& key,const V& value)
    		:_key(key)
    		,_value(value)
    		,_left(NULL)
    		,_right(NULL)
    	{}
    
    	K _key;
    	V _value;
    	BSTreeNode<K,V>* _left;
    	BSTreeNode<K,V>* _right;
    };
    
    template<class K,class V>
    class BSTree
    {
    	typedef BSTreeNode<K,V> Node;
    public:
    	BSTree()
    		:_root(NULL)
    	{}
    	bool Insert(const K& key,const V& value)
    	{
    		if(_root == NULL)
    		{
    			_root = new Node(key,value);
    		}
    		Node* cur = _root;
    		Node* parent  = NULL;
    		while(cur)
    		{
    			if(cur->_key < key)
    			{
    				parent = cur;
    				cur = cur->_right;
    			}
    			else if(cur->_key > key)
    			{
    				parent = cur;
    				cur = cur->_left;
    			}
    			else
    				return false;
    		}
    		cur =  new Node(key,value);
    		if(parent->_key < key)
    		{
    			parent->_right = cur;
    		}
    		else
    		{
    			parent->_left = cur;
    		}
    		return true;
    	}
    
    	Node* Find(const K& key)
    	{
    		Node* cur = _root;
    		while(cur)
    		{
    			if(cur->_key < key)
    				cur =  cur->_right;
    			else if(cur->_key > key)
    				cur = cur->_left;
    			else
    			{
    				cout<<cur->_key<<":"<<cur->_value<<endl;
    				return cur;
    			}
    		}
    		return NULL;
    	}
    
    	bool Remove(const K& key)
    	{
    		if(_root == NULL)
    		{
    			return false;
    		}
    		Node* cur =  _root;
    		Node* parent = NULL;
    		//找到要删除的节点
    		while(cur)
    		{
    			if(cur->_key > key)
    			{
    				parent = cur;
    				cur = cur->_left;
    			}
    			else if(cur->_key < key)
    			{
    				parent = cur;
    				cur =  cur->_right;
    			}
    			else
    			{
    				break;
    			}
    		}
    		Node* del = NULL;
    		//1.要删除节点的左孩子或者右孩子为空
    		if(cur->_left == NULL)
    		{
    			del = cur;
    			if(parent->_left == cur)
    			{
    				parent->_left = cur->_right;
    			}
    			else
    			{
    				parent->_right = cur->_right;
    			}
    			delete del;
    		}
    		//删除节点的右孩子为空
    		else if(cur->_right == NULL) 
    		{
    			del = cur;
    			if(parent->_left == cur)
    			{
    				parent->_left = cur->_left;
    			}
    			else
    			{
    				parent->_right = cur->_left;
    			}
    			delete del;
    		}
    		// //找以该节点为根节点的左边(最大的)最右的孩子代替它,然后删除
    		else		//要删除节点的左右孩子都不为空
    		{
    			parent = cur;
    			//找以该节点为根节点的右边(最小的)最左的孩子代替它,然后删除
    			Node* subLeft = cur->_right;
    			while(subLeft->_left)
    			{
    				parent = subLeft;
    				subLeft =  subLeft->_left;
    			}
    			cur->_key = subLeft->_key;
    			cur->_value = subLeft->_value;
    
    			if(parent->_left == subLeft)
    				parent->_left = subLeft->_right;
    			else
    				parent->_right = subLeft->_right;
    			delete subLeft;
    		}
    		return false;
    	}
    
    	//递归插入
    	bool InsertR(const K& key,const V& value)
    	{
    		return _InsertR(_root,key,value);
    	}
    	//递归删除
    	bool RemoveR(const K& key)
    	{
    		return _RemoveR(_root,key);	
    	}
    	//递归查找
    	Node* FindR(const K& key)
    	{
    		return _FindR(_root,key);
    	}
    
    	void InOrder()
    	{
    		_InOrder(_root);
    		cout<<endl;
    	}
    protected:
    	bool _InsertR(Node*& root,const K& key,const V& value)
    	{	
    		if(root == NULL)
    		{
    			root = new Node(key,value);
    			return true;
    		}
    		if(root->_key > key)
    		{
    			return _InsertR(root->_left,key,value);
    		}
    		else if(root->_key < key)
    		{
    			return _InsertR(root->_right,key,value);
    		}
    		else
    		{
    			return false;			
    		}
    	}
    	//递归的删除一个节点
    	bool _RemoveR(Node*& root,const K& key)
    	{
    		if(root == NULL)
    		{
    			return false;
    		}
    		if(root->_key < key)
    		{
    			_RemoveR(root->_right,key);
    		}
    		else if(root->_key > key)
    		{
    			_RemoveR(root->_left,key);
    		}
    		else
    		{
    			Node* del = root;
    			if(root->_left == NULL)
    			{
    				root = root->_right;
    			}
    			else if(root->_right == NULL)
    			{
    				root = root->_left;
    			}
    			else
    			{
    				Node* subLeft = root->_right;
    				while(subLeft->_left)
    				{
    					subLeft = subLeft->_left;
    				}
    				swap(root->_key,subLeft->_key);
    				swap(root->_value,subLeft->_value);
    				return _RemoveR(root->_right,key);
    			}
    			delete del;
    		}
    		return true;
    	}
    
    	Node* _FindR(Node*& root,const K& key)
    	{
    		if(_root == NULL)
    		{
    			return NULL;
    		}
    		if(root->_key > key)
    		{
    			_FindR(root->_left,key);
    		}
    		else if(root->_key < key)
    		{
    			_FindR(root->_right,key);
    		}
    		else
    		{
    			cout<<root->_key<<":"<<root->_value<<endl;
    			return root;
    		}
    		return NULL;
    	}
    
    	void _InOrder(Node* root)
    	{
    		if(root == NULL)
    		{
    			return;
    		}
    		_InOrder(root->_left);
    		cout<<root->_key<<" ";
    		_InOrder(root->_right);	
    	}
    protected:
    	Node* _root;
    };
    
    //测试迭代
    void TestTree()
    {
    	BSTree<int ,int> bst;
    	int a[] = {5,3,7,1,4,6,8,0,2,9};
    	for(size_t i = 0; i < sizeof(a)/sizeof(a[0]); i++)
    	{
    		bst.Insert(a[i],i);
    	}
    	bst.InOrder();
    	BSTreeNode<int,int>* ret = bst.Find(6);
    	bst.Remove(9);
    	bst.InOrder();
    	bst.Remove(7);
    	bst.InOrder();
    	bst.Remove(5);
    	bst.InOrder();
    	bst.Remove(3);
    	bst.InOrder();
    }
    
    //测试递归
    void TestTreeR()
    {
    	BSTree<int ,int> bst1;
    	int a1[] = {5,3,7,1,4,6,8,0,2,9};
    	for(size_t i = 0; i < sizeof(a1)/sizeof(a1[0]); i++)
    	{
    		bst1.InsertR(a1[i],i);
    	}
    	bst1.InOrder();
    	BSTreeNode<int,int>* ret1 = bst1.FindR(6);
    	bst1.RemoveR(9);
    	bst1.InOrder();
    	bst1.RemoveR(5);
    	bst1.InOrder();
    	bst1.RemoveR(3);
    	bst1.InOrder();
    	bst1.RemoveR(7);
    	bst1.InOrder();
    	bst1.RemoveR(8);
    	bst1.InOrder();
    	bst1.RemoveR(2);
    	bst1.InOrder();
    	bst1.RemoveR(6);
    	bst1.InOrder();
    }

    //Test.cpp
    
    #include<iostream>
    using namespace std;
    #include"BSTree.h"
    
    int main()
    {
    	//TestTree();
    	TestTreeR();
    	getchar();
    	return 0;
    }

### 于 PTA 平台上二叉搜索树的相练习题及其解法 #### 了解二叉搜索树的基础概念 在深入探讨具体的练习之前,重要的是要理解什么是二叉搜索树(BST)。这是一种特殊的二叉树,在这种树中,对于任意节点而言,左子树中的所有键值小于该节点的键值;右子树中的所有键值大于该节点的键值[^1]。 #### 构二叉搜索树BST的过程涉及按照特定顺序插入新元素。每当有新的数值加入时,程序会从根部开始遍历整棵树直到找到合适的位置放置这个数。如果当前考察位置为空,则直接在此处创一个新的叶子节点来容纳待插入的数据项。这一过程不仅有助于掌握基本的操作技能,而且可以增强对数据结构内部机制的认识。 #### 寻找共同祖先问题 当面对诸如“求两个指定节点之间的最低公共祖先”的挑战时,一种有效的方法是从根向下追踪路径直至遇到任一目标节点为止,并记录沿途访问过的每一个节点作为候选者。接着继续探索另一条分支并重复上述动作。最终对比两条路线所遇见过的所有节点集合,其中最深的那个交集成员即是答案所在之处[^3]。 ```python class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right def lowestCommonAncestor(root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': if not root or root == p or root == q: return root left_search_result = lowestCommonAncestor(root.left, p, q) right_search_result = lowestCommonAncestor(root.right, p, q) if left_search_result and right_search_result: return root elif left_search_result: return left_search_result else: return right_search_result ``` 此代片段展示了如何实现寻找最小公共祖先的功能。它采用递归的方式分别检查左右两侧是否存在所需的目标节点pq。一旦发现两者皆存在于不同方向之下,则说明当前处理的对象正是它们之间最近的一个共有前辈。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值