【深入C++】二叉搜索树
创始人
2024-12-23 17:03:55
0

文章目录

  • 什么是二叉搜索树
  • 二叉搜索树的接口
    • 1.查找操作
    • 2.插入操作
    • 3.中序遍历
    • 4.删除操作
  • 所有代码
  • 总结

在这里插入图片描述

在这里插入图片描述

什么是二叉搜索树

二叉搜索树(Binary Search Tree, BST)是一种特殊的二叉树,其每个节点最多有两个子节点,分别称为左子节点和右子节点。BST具有以下性质:

  1. 左子树的所有节点值都小于根节点的值:即对于每一个节点,其左子树上所有节点的值都比该节点的值小。
  2. 右子树的所有节点值都大于根节点的值:即对于每一个节点,其右子树上所有节点的值都比该节点的值大。
  3. 每个子树也是二叉搜索树:这意味着BST的定义在每个节点的子树上都成立。

形如下面这棵树就是一颗二叉搜索树:

       8      /   \     3     10    / \      \   1   6      14      / \     /     4   7   13  

二叉搜索树的接口

要写二叉搜索树的接口,我们先得定义一颗二叉搜索树:

定义二叉搜索树的节点:

template struct BSTreeNode { 	K _key; 	BSTreeNode* _left; 	BSTreeNode* _right; 	BSTreeNode(const K& key):_key(key), _left(nullptr), _right(nullptr){} }; 

定义二叉搜索树:

template class BSTree { 	typedef BSTreeNode Node; public: private: 	Node* _root = nullptr; }; 

1.查找操作

由于二叉搜索树的性质,所以这里我们可以直接用while循环来查找,不需要进行递归来查找:

bool Find(const K& key) { 	Node* cur = _root; 	while (cur) 	{ 		//小于当前节点,在左子树 		if (cur->_key > key)cur = cur->_left; 		//大于当前节点,在右子树 		else if (cur->_key < key) cur = cur->_right; 		//等于当前节点,返回true 		else return true; 	} 	return false; } 

2.插入操作

插入操作我们只需要找到插入的位置,然后插入节点即可,如果没有找到,则返回false,如果找到了并成功插入了,则返回true。

bool Insert(const K& key) { 	//没有根节点的情况 	if (_root == nullptr) 	{ 		_root = new Node(key); 		return true; 	} 	//遍历节点 	Node* cur = _root; 	//记录当前节点的父节点 	Node* parent = nullptr; 	while (cur) 	{ 		parent = cur; 		if (cur->_key > key)cur = cur->_left; 		else if (cur->_key < key) cur = cur->_right; 		else return false; 	} 	//找到插入的地方,直接new 	cur = new Node(key); 	//判断插入到父节点的左节点还是右节点 	if (parent->_key < key) parent->_right = cur; 	else parent->_left = cur; 	return true; } 

3.中序遍历

对于中序遍历,我们需要写一个辅助函数,来传递当前this指针对应的root。

void InOrder() { 	_InOrder(_root); } void _InOrder(Node* root) { 	if (root == nullptr) return; 	_InOrder(root->_left); 	cout << root->_key << ' '; 	_InOrder(root->_right); } 

4.删除操作

插入操作分三种情况:
在这里插入图片描述
我们拿下面这个二叉搜索树为例子:
在这里插入图片描述

将节点进行归类:
在这里插入图片描述
我们先讨论删除没有孩子的节点,对于没有孩子的节点我们可以直接进行删除。
其次,我们来讨论删除一个孩子的节点,假如我们删除14,我们需要知道14的父亲,将10和14的左孩子串起来。
在这里插入图片描述
可以将一个孩子的节点归结为这几种情况。
接下来就是有两个孩子的节点:
在这里插入图片描述
我们拿3这个节点为例子:
在这里插入图片描述

删除3节点,我们应该用左子树最大,或者右子树最小进行替换,然后转化成删除左子树最大,或者右子树最小的节点,就相当于把删除有两个孩子的节点转换成删除一个孩子的节点或者没有孩子的节点。

bool Erase(const K& key) { 	//三种情况: 	//1.一个孩子 	//2.没有孩子 	//3.两个孩子:左子树的最大,右子树的最小 	//左子树的最左,右子树的最右 	Node* cur = _root; 	Node* parent = nullptr; 	while (cur) 	{ 		if (cur->_key > key) 		{ 			parent = cur; 			cur = cur->_left; 		} 		else if (cur->_key < key) 		{ 			parent = cur; 			cur = cur->_right; 		} 		else 		{ 			//删除 			//0-1个孩子的情况 			if (cur->_left == nullptr) 			{ 				//删除根节点的情况 				if (parent == nullptr)_root = cur->_right; 				else 				{ 					if (parent->_left == cur) parent->_left = cur->_right; 					else parent->_right = cur->_right; 				} 				delete cur; 				return true; 			} 			else if (cur->_right == nullptr) 			{ 				//删除根节点 				if (parent == nullptr) _root = cur->_left; 				else 				{ 					if (parent->_left == cur)parent->_left = cur->_left; 					else parent->_left = cur->_left; 				} 				delete cur; 				return true; 			} 			//两个孩子的情况 			else 			{ 				//找右子树最小的节点作为最大的节点 				Node* rightminp = nullptr; 				Node* rightmin = cur->_right; 				//left不为空就一直向left走 				while (rightmin->_left != nullptr) 				{ 					rightminp = rightmin; 					rightmin = rightmin->_left; 				} 				cur->_key = rightmin->_key; 				if (rightminp != nullptr) rightminp->_left = rightmin->_right; 				else cur->_right = rightmin->_right; 				delete rightmin; 				return true; 			}  		} 	} 	return false; } 

删除成功返回true,删除失败没找到则返回false。

所有代码

#pragma once #include using namespace std; template struct BSTreeNode { 	K _key; 	BSTreeNode* _left; 	BSTreeNode* _right; 	BSTreeNode(const K& key):_key(key), _left(nullptr), _right(nullptr){} };  template class BSTree { 	typedef BSTreeNode Node; public: 	bool Insert(const K& key) 	{ 		if (_root == nullptr) 		{ 			_root = new Node(key); 			return true; 		} 		Node* cur = _root; 		Node* parent = nullptr; 		while (cur) 		{ 			parent = cur; 			if (cur->_key > key)cur = cur->_left; 			else if (cur->_key < key) cur = cur->_right; 			else return false; 		} 		cur = new Node(key); 		if (parent->_key < key) parent->_right = cur; 		else parent->_left = cur; 		return true; 	} 	bool Find(const K& key) 	{ 		Node* cur = _root; 		while (cur) 		{ 			if (cur->_key > key)cur = cur->_left; 			else if (cur->_key < key) cur = cur->_right; 			else return true; 		} 		return false; 	}  	bool Erase(const K& key) 	{ 		//三种情况: 		//1.一个孩子 		//2.没有孩子 		//3.两个孩子:左子树的最大,右子树的最小 		//左子树的最左,右子树的最右 		Node* cur = _root; 		Node* parent = nullptr; 		while (cur) 		{ 			if (cur->_key > key) 			{ 				parent = cur; 				cur = cur->_left; 			} 			else if (cur->_key < key) 			{ 				parent = cur; 				cur = cur->_right; 			} 			else 			{ 				//删除 				//0-1个孩子的情况 				if (cur->_left == nullptr) 				{ 					//删除根节点的情况 					if (parent == nullptr)_root = cur->_right; 					else 					{ 						if (parent->_left == cur) parent->_left = cur->_right; 						else parent->_right = cur->_right; 					} 					delete cur; 					return true; 				} 				else if (cur->_right == nullptr) 				{ 					//删除根节点 					if (parent == nullptr) _root = cur->_left; 					else 					{ 						if (parent->_left == cur)parent->_left = cur->_left; 						else parent->_left = cur->_left; 					} 					delete cur; 					return true; 				} 				//两个孩子的情况 				else 				{ 					//找右子树最小的节点作为最大的节点 					Node* rightminp = nullptr; 					Node* rightmin = cur->_right; 					//left不为空就一直向left走 					while (rightmin->_left != nullptr) 					{ 						rightminp = rightmin; 						rightmin = rightmin->_left; 					} 					cur->_key = rightmin->_key; 					if (rightminp != nullptr) rightminp->_left = rightmin->_right; 					else cur->_right = rightmin->_right; 					delete rightmin; 					return true; 				}  			} 		} 		return false; 	} 	void InOrder() 	{ 		_InOrder(_root); 	} private: 	void _InOrder(Node* root) 	{ 		if (root == nullptr) return; 		_InOrder(root->_left); 		cout << root->_key << ' '; 		_InOrder(root->_right); 	} 	Node* _root = nullptr; }; 

总结

二叉搜索树(BST)是一种在计算机科学中广泛应用的数据结构,具有高效的查找、插入和删除操作。通过遵循节点值的有序性规则,BST能够在平均情况下实现对数时间复杂度的操作,使其成为处理动态数据集的理想选择。

在本篇博客中,我们详细介绍了二叉搜索树的定义和性质,并通过示例展示了其基本结构。我们还探讨了BST的三大主要操作:插入、查找和删除,并分析了这些操作的实现方法和时间复杂度。

尽管二叉搜索树在平衡状态下具有高效的性能,但在最坏情况下,BST可能会退化成链表。因此,在实际应用中,经常需要采用自平衡二叉搜索树(如AVL树和红黑树)来保证其性能。

通过对BST的深入理解和实践,相信你能够在各种编程场景中灵活运用这一重要的数据结构,从而提高程序的效率和性能。如果你对二叉搜索树有任何疑问或希望了解更多高级应用,欢迎在评论区留言讨论。

相关内容

热门资讯

一分钟秒懂,微信金花怎么玩哪里... 新永和是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:160470940许多玩家在游戏中会购买房卡来...
秒懂百科,斗牛房卡在哪购买海贝... 海贝之城是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:44346008许多玩家在游戏中会购买房卡来...
带你快速了解,牛牛链接房卡在哪... 新速度是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:86909166许多玩家在游戏中会购买房卡来享...
8分钟了解,炸金花房卡链接哪里... 海贝之城是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:86909166许多玩家在游戏中会购买房卡来...
科技实测,炸金花房卡链接在哪弄... 微信斗牛是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:86909166许多玩家在游戏中会购买房卡来...
三分钟讲述,牛牛房卡卖家联系方... 微信炸金花是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:160470940许多玩家在游戏中会购买房...
全攻略普及,金花房卡从哪里购买... 皇豪互众是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:44346008许多玩家在游戏中会购买房卡来...
一分钟介绍推荐,微信斗牛房卡专... 新祥心牛牛是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:86909166许多玩家在游戏中会购买房卡...
一分钟教会你,哪里有卖微信炸金... 微信炸金花是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:160470940许多玩家在游戏中会购买房...
秒懂百科,微信链接斗牛房卡多少... 微信斗牛是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:160470940许多玩家在游戏中会购买房卡...
详细房卡教程,微信斗牛房卡怎么... 微信斗牛是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:86909166许多玩家在游戏中会购买房卡来...
分享教程,买房卡的金花房代理联... 微信炸金花是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:15984933许多玩家在游戏中会购买房卡...
一分钟秒懂,微信群链接牛牛买房... 微信炸金花是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:160470940许多玩家在游戏中会购买房...
一分钟教会你,哪里有卖微信炸金... 微信炸金花是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:44346008许多玩家在游戏中会购买房卡...
一分钟发现,微信牛牛房卡哪里买... 斗牛是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:44346008许多玩家在游戏中会购买房卡来享受...
一分钟发现,微信上金花房卡怎么... 新老夫子是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:44346008许多玩家在游戏中会购买房卡来...
一分钟实测分享,微信金花房卡招... 新神盾是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:44346008许多玩家在游戏中会购买房卡来享...
全网内容,软件炸金花模式创建开... 微信炸金花是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:44346008许多玩家在游戏中会购买房卡...
玩家必备攻略,金花房卡从哪里购... 金牛座金花是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:44346008许多玩家在游戏中会购买房卡...
玩家分享,金花大厅链接房卡怎么... 炫酷大厅是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:86909166许多玩家在游戏中会购买房卡来...