数据结构——二叉搜索树

一、概念

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

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

二、二叉搜索树的操作

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树和红黑树中解决。请大家继续锁定,精彩不停更!!!

相关推荐
福大大架构师每日一题22 分钟前
文心一言 VS 讯飞星火 VS chatgpt (396)-- 算法导论25.2 1题
算法·文心一言
EterNity_TiMe_36 分钟前
【论文复现】(CLIP)文本也能和图像配对
python·学习·算法·性能优化·数据分析·clip
机器学习之心1 小时前
一区北方苍鹰算法优化+创新改进Transformer!NGO-Transformer-LSTM多变量回归预测
算法·lstm·transformer·北方苍鹰算法优化·多变量回归预测·ngo-transformer
yyt_cdeyyds1 小时前
FIFO和LRU算法实现操作系统中主存管理
算法
daiyang123...1 小时前
测试岗位应该学什么
数据结构
alphaTao1 小时前
LeetCode 每日一题 2024/11/18-2024/11/24
算法·leetcode
kitesxian2 小时前
Leetcode448. 找到所有数组中消失的数字(HOT100)+Leetcode139. 单词拆分(HOT100)
数据结构·算法·leetcode
VertexGeek2 小时前
Rust学习(八):异常处理和宏编程:
学习·算法·rust
石小石Orz2 小时前
Three.js + AI:AI 算法生成 3D 萤火虫飞舞效果~
javascript·人工智能·算法
jiao_mrswang3 小时前
leetcode-18-四数之和
算法·leetcode·职场和发展