数据结构——二叉搜索树

一、概念

二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:

  • 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
  • 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
  • 它的左右子树也分别为二叉搜索树

二、二叉搜索树的操作

2.1 查找

  1. 从根开始比较,比根大的向右边走查找,比根小的向左边走查找
  2. 最多查找高度次,走到空还没有找到的,这个值就不存在

2.2 插入

插入的具体过程为:

  1. 树为空,则直接新增节点,赋值给root节点
  2. 树不空,按二号搜索树性质查找插入位置,插入新节点

2.3 删除

首先查找元素是否在二叉搜索树中,如果不存在,则返回,否则要删除的节点可能有下面四种情况:

  1. 要删除的节点无孩子节点
  2. 要删除的节点只有左孩子结点
  3. 要删除的节点只有右孩子节点
  4. 要删除的节点有左、右孩子节点

看起来有待删除的节点有4种情况,实际情况1可以与情况2或者3合并起来,因此真正的情况如下:

  • 删除该节点且使被删除节点的双亲节点指向被删除节点的左孩子节点------直接删除
  • 删除该节点且使被删除节点的双亲节点指向被删除节点的右孩子节点------直接删除
  • 在它的右子树中寻找中序下的第一个节点(关键码最小),用它的值填补到被删除节点中,再来处理该节点的删除问题------替换法删除

三、二叉搜索树的实现

cpp 复制代码
template<class T>
struct BSTNode
{
	BSTNode(const T& data = T())
		: _pLeft(nullptr), _pRight(nullptr), _data(data)
	{}
	BSTNode<T>* _pLeft;
	BSTNode<T>* _pRight;
	T _data;
};

template<class T>
class BSTree
{
	typedef BSTNode<T> Node;
	typedef Node* PNode;
public:
	BSTree() : _pRoot(nullptr)
	{}
private:
	PNode _pRoot;
};

3.1 插入

cpp 复制代码
// 插入
	bool Insert(const T& data)
	{
		
		if (nullptr == _pRoot)
		{
			_pRoot = new Node(data);
			return true;
		}
		
		PNode pCur = _pRoot;
		
		PNode pParent = nullptr;
		while (pCur)
		{
			pParent = pCur;
			if (data < pCur->_data)
				pCur = pCur->_pLeft;
			else if (data > pCur->_data)
				pCur = pCur->_pRight;
			else
				return false;
		}

		pCur = new Node(data);
		if (data < pParent->_data)
			pParent->_pLeft = pCur;
		else
			pParent->_pRight = pCur;
		return true;
	}

	

3.2 删除

cpp 复制代码
// 删除
	bool Erase(const T& data)
	{
		if (nullptr == _pRoot)
			return false;

		PNode pCur = _pRoot;
		PNode pParent = nullptr;
		while (pCur)
		{
			if (data == pCur->_data)
				break;
			else if (data < pCur->_data)
			{
				pParent = pCur;
				pCur = pCur->_pLeft;
			}
			else
			{
				pParent = pCur;
				pCur = pCur->_pRight;
			}
		}

		if (nullptr == pCur)
			return false;

		return true;
	}

四、二叉搜索树的性能分析

插入和删除操作都必须先查找,查找效率代表了二叉搜索树中各个操作的性能。

对有n个节点的二叉搜索树,若每个元素查找的概率相等,则二叉搜索树平均查找长度是节点在二叉搜索树的深度的函数,即节点越深,比较次数越多。

但对于同一个关键码集合 ,如果各关键码插入的次序不同 ,可能得到不同结构的二叉搜索树。
最优情况下,二叉搜索树为完全二叉树(或者接近完全二叉树),其时间复杂度为O(logN)

最差情况下,二叉搜索树退化为单支树(或者类似单支),其时间复杂度为O(N)

那么问题来了,如果退化为单支树,二叉搜索树的优势就失去了,该怎么进行改进,使不论什么次序插入关键码,二叉搜索树的性能都能达到最优呢?这个会在后续AVL树和红黑树中解决。请大家继续锁定,精彩不停更!!!

相关推荐
古希腊掌管学习的神10 分钟前
[搜广推]王树森推荐系统笔记——曝光过滤 & Bloom Filter
算法·推荐算法
qystca11 分钟前
洛谷 P1706 全排列问题 C语言
算法
浊酒南街17 分钟前
决策树(理论知识1)
算法·决策树·机器学习
就爱学编程24 分钟前
重生之我在异世界学编程之C语言小项目:通讯录
c语言·开发语言·数据结构·算法
学术头条29 分钟前
清华、智谱团队:探索 RLHF 的 scaling laws
人工智能·深度学习·算法·机器学习·语言模型·计算语言学
Schwertlilien1 小时前
图像处理-Ch4-频率域处理
算法
IT猿手1 小时前
最新高性能多目标优化算法:多目标麋鹿优化算法(MOEHO)求解TP1-TP10及工程应用---盘式制动器设计,提供完整MATLAB代码
开发语言·深度学习·算法·机器学习·matlab·多目标算法
__lost1 小时前
MATLAB直接推导函数的导函数和积分形式(具体方法和用例)
数学·算法·matlab·微积分·高等数学
thesky1234561 小时前
活着就好20241224
学习·算法
ALISHENGYA1 小时前
全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之分支结构(实战项目二)
数据结构·c++·算法