一个简易的二叉搜索树实现

namespace k
{
	template<class K>
	struct TreeNode
	{
		TreeNode(K key)
			:left(nullptr), right(nullptr),_key(key)
		{}
		
		TreeNode<K>* left;
		TreeNode<K>* right;
		K _key;
	};

	template<class K>
	class BsTree
	{
	public:
		typedef TreeNode<K> Node;
		bool Insert(const K& key)//插入
		{
			if (_root == nullptr)
			{
				_root = new Node(key);
				return true;
			}
			Node* cur = _root;
			Node* prt = nullptr;
			//用一个prt变量记录插入位置的父亲节点
			while (cur)
			{
				if (cur->_key < key)
				{
					prt = cur;
					cur = cur->right;
				}
				else if (cur->_key > key)
				{
					prt = cur;
					cur = cur->left;
				}
				else
				{
					return false;
				}
			}
			cur = new Node(key);
			//让父亲节点指向新插入的节点
			if (prt->_key < key)
			{
				prt->right = cur;
			}
			else
			{
				prt->left = cur;
			}
			return true;
		}

		bool Find(const K& key)
		{
			Node* cur = _root;
			while (cur)
			{
				if (key > cur->_key)
				{
					cur = cur->right;
				}
				else if (key < cur->_key)
				{
					cur = cur->left;
				}
				else
				{
					return true;
				}
			}
			return false;
		}

		bool Erase(const K& key)
		{
			//需要一个prt节点保存删除元素的父亲节点,用于后续连接
			Node* prt = nullptr;
			Node* cur = _root;
			while (cur)
			{
				if (cur->_key < key)
				{
					prt = cur;
					cur = cur->right;
				}
				else if (cur->_key > key)
				{
					prt = cur;
					cur = cur->left;
				}
				else//找到了,开始删除
				{
					//左为空,则父亲指向右
					if (cur->left == nullptr)
					{
						//如果cur为根节点,让根节点等于右
						if (cur == _root)
						{
							_root = cur->right;
						}
						else
						{
							if (cur == prt->left)
							{
								prt->left = cur->right;//cur为父亲的左则让父亲的左指向右
							}
							else
							{
								prt->right = cur->right;//cur为父亲的右则让父亲的右指向右
							}
						}
						delete cur;
					}//右为空,则父亲指向左,具体做法与上类似
					else if (cur->right == nullptr)
					{
						if (cur == _root)
						{
							_root = cur->left;
						}
						else
						{
							if (cur == prt->left)
							{
								prt->left = cur->left;
							}
							else
							{
								prt->right = cur->left;
							}
						}
						
						delete cur;
					}
					else//cur的两边都不为空
					{
						Node* RightMinPrt = cur;
						Node* RightMin = cur->right;
						//寻找cur的右树中最小值,并记录最小值的父亲。
						while (RightMin->left)
						{
							RightMinPrt = RightMin;
							RightMin = RightMin->left;
						}
						cur->_key = RightMin->_key;
						if (RightMin == RightMinPrt->right)//最小值为最小值父亲的右节点
						{
							RightMinPrt->right = RightMin->right;
						}
						else//最小值为最小值父亲的左节点
							RightMinPrt->left = RightMin->right;
						delete RightMin;
					}
					return true;
				}
			}
			return false;
		}

		void _Inorder(Node* N)
		{
			if (N == nullptr)
			{
				return;
			}
			_Inorder(N->left);
			cout << N->_key << " ";
			_Inorder(N->right);
		}
		//打印这棵树
		void Inorder()
		{
			_Inorder(_root);
			cout << endl;
		}
	private:
		Node* _root = nullptr;
	};
}

运行一下。

int main()
{
	k::BsTree<int> t;
	int arr[] = { 5,3,4,1,7,8,2,6,0,9 };
	for (auto e : arr)
	{
		t.Insert(e);
	}
	t.Inorder();

	for (auto e : arr)
	{
		t.Erase(e);
		t.Inorder();
	}
	
	return 0;
}

        以上是一个key模型,下面还有一个key value模型的实现

namespace k
{
	template<class K, class V>
	struct TreeNode
	{
		TreeNode(const K& key, const V& value)
			:left(nullptr), right(nullptr),_key(key), _value(value)
		{}
		
		TreeNode<K, V>* left;
		TreeNode<K, V>* right;
		K _key;
		V _value;
	};

	template<class K, class V>
	class BsTree
	{
	public:
		typedef TreeNode<K, V> Node;
		bool Insert(const K& key, const V& value)//插入
		{
			if (_root == nullptr)
			{
				_root = new Node(key, value);
				return true;
			}
			Node* cur = _root;
			Node* prt = nullptr;
			//用一个prt变量记录插入位置的父亲节点
			while (cur)
			{
				if (cur->_key < key)
				{
					prt = cur;
					cur = cur->right;
				}
				else if (cur->_key > key)
				{
					prt = cur;
					cur = cur->left;
				}
				else
				{
					return false;
				}
			}
			cur = new Node(key, value);
			//让父亲节点指向新插入的节点
			if (prt->_key < key)
			{
				prt->right = cur;
			}
			else
			{
				prt->left = cur;
			}
			return true;
		}

		Node* Find(const K& key)
		{
			Node* cur = _root;
			while (cur)
			{
				if (key > cur->_key)
				{
					cur = cur->right;
				}
				else if (key < cur->_key)
				{
					cur = cur->left;
				}
				else
				{
					return cur;
				}
			}
			return nullptr;
		}

		bool Erase(const K& key)
		{
			//需要一个prt节点保存删除元素的父亲节点,用于后续连接
			Node* prt = nullptr;
			Node* cur = _root;
			while (cur)
			{
				if (cur->_key < key)
				{
					prt = cur;
					cur = cur->right;
				}
				else if (cur->_key > key)
				{
					prt = cur;
					cur = cur->left;
				}
				else//找到了,开始删除
				{
					//左为空,则父亲指向右
					if (cur->left == nullptr)
					{
						//如果cur为根节点,让根节点等于右
						if (cur == _root)
						{
							_root = cur->right;
						}
						else
						{
							if (cur == prt->left)
							{
								prt->left = cur->right;//cur为父亲的左则让父亲的左指向右
							}
							else
							{
								prt->right = cur->right;//cur为父亲的右则让父亲的右指向右
							}
						}
						delete cur;
					}//右为空,则父亲指向左,具体做法与上类似
					else if (cur->right == nullptr)
					{
						if (cur == _root)
						{
							_root = cur->left;
						}
						else
						{
							if (cur == prt->left)
							{
								prt->left = cur->left;
							}
							else
							{
								prt->right = cur->left;
							}
						}
						
						delete cur;
					}
					else//cur的两边都不为空
					{
						Node* RightMinPrt = cur;
						Node* RightMin = cur->right;
						//寻找cur的右树中最小值,并记录最小值的父亲。
						while (RightMin->left)
						{
							RightMinPrt = RightMin;
							RightMin = RightMin->left;
						}
						cur->_key = RightMin->_key;
						if (RightMin == RightMinPrt->right)//最小值为最小值父亲的右节点
						{
							RightMinPrt->right = RightMin->right;
						}
						else//最小值为最小值父亲的左节点
							RightMinPrt->left = RightMin->right;
						delete RightMin;
					}
					return true;
				}
			}
			return false;
		}

		void _Inorder(Node* N)
		{
			if (N == nullptr)
			{
				return;
			}
			_Inorder(N->left);
			cout << N->_key << " ";
			_Inorder(N->right);
		}
		//打印这棵树
		void Inorder()
		{
			_Inorder(_root);
			cout << endl;
		}
	private:
		Node* _root = nullptr;
	};
}

        二叉搜索树在插入数据有序的情况下,访问效率是O(N),效率不够好。解决方法为设计成红黑树或者AVL树。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值