二叉搜索树

概念

二叉搜索树又称二叉排序树 或者是一个空树

特点
  • 左子树所有节点的值都小于根节点的值,右子树所有节点的值都大于根节点的值

  • 它的左右子树也分别为二叉搜索树

  • 解决了数组插入删除数据时的效率问题,并且衍生出AVL树,红黑树,B树系列

时间复杂度O(n)

格式

二叉搜索树的查找
  • 从根开始比较,查找,比根大向右边找,反之向左
  • 最多查找高度次,若走到空,则值不存在
二叉查找树的插入
  • 树为空,新增节点,赋值root
  • 树不为空,查找+插入新节点
二叉查找树的删除
  • 要删除的节点无子节点
  • 要删除的节点只有左节点
    • 该节点的parent指向待删节点的左节点,删除待删节点
  • 要删除的节点只有右节点
    • 该节点的parent指向待删节点的右节点,删除待删节点
  • 要删除的节点有左右节点
    • 在它的左子树中寻找最大的节点和它的parent,交换待删节点和这个最大节点,用parent删除该待删节点,并指向这个待删节点的左节点
非递归版:
cpp 复制代码
template<class K, class V>
struct BSTreeNode
{
	BSTreeNode(const K& key, const V& val) :_left(nullptr), _right(nullptr), _key(key), _val(val) {}

	BSTreeNode<K, V>* _left;
	BSTreeNode<K, V>* _right;
	K _key;
	V _val;
};
template<class K, class V>
class BSTree
{
	typedef BSTreeNode<K, V> Node;
public:
	void InOrder()
	{
		_InOrder(_root);
		cout << endl;
	}
	void _InOrder(Node* root)
	{
		if (root == nullptr) return;
		_InOrder(root->_left);
		cout << root->_key << " " << root->_val;
		_InOrder(root->_right);
	}
	Node* Insert(const K& key, const V& value)
	{
		if (_root == nullptr)
		{
			_root = new Node(key, value);
			return _root;
		}
		Node* parent = nullptr;
		Node* cur = _root;
		while (cur)
		{
			if (key > cur->_key)
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (key < cur->_key)
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				return nullptr;
			}
		}
		cur = new Node(key, value);
		if (key > parent->_key) parent->_right = cur;
		else if (key < parent->_key)
		{
			parent->_left = cur;
		}
		return _root;
	}
public:
	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)
	{
		Node* parent = nullptr;
		Node* cur = _root;

		while (cur)
		{
			if (key > cur->_key) parent = cur,cur = cur->_right;
			else if (key < cur->key) parent = cur,cur = cur->_left;
			else
			{
				if (cur->_left == nullptr)
				{
					if (cur == _root) _root = cur->_right;
					else
					{
						if (parent->_right == cur) parent->_right = cur->_right;
						else parent->_left = cur->_right;
					}
				}
				else if (cur->_right = nullptr)
				{
					if (cur == _root) _root = cur->left;
					else
					{
						if (parent->_right == cur) parent->_right = cur->left;
						else parent->_left = cur->_left;
					}
				}
				else
				{
					Node* parent = cur;
					Node* leftMax = cur->_left;
					while (leftMax->_right)
					{
						parent = leftMax;
						leftMax = leftMax->_right;
					}
					swap(cur->_key, leftMax->_key);
					if (parent->_left == leftMax)
					{
						parent->_left = leftMax->_left;
					}
					else parent->_right = leftMax->_left;
					cur = leftMax;
				}
				delete cur;
				return true;
			}
		}
		return false;
	}
	
	
private:
	Node* _root = nullptr;
};
递归版:
  • 解析insert
cpp 复制代码
bool InsertR(const K& key)
{
	return _InsertR(_root, key);
}

bool _InsertR(Node*& root ,const K& key)
{
	if (root == nullptr)
	{
		root = new Node(key);
		return true;
	}
	if (key > root->_key) return _InsertR(root->_right, key);
	else if (key < root->_key) return _InsertR(root->_left, key);
	else return false;
}

当传入根节点时,调用_InsertR开始向下找值

  • Erase函数
cpp 复制代码
bool EraseR(const K& key)
{
	return _EraseR(_root, key);
}
bool _EraseR(Node*& root, const K& key)
{
	if (root == nullptr) return false;
	if (key > root->_key) return _EraseR(root->_right, key);
	else if (key < root->_key) return _EraseR(root->_left, key);
	else
	{
		Node* del = root;
		//左为空
		if (root->_left == nullptr) root = root->_right;
		//右为空
		else if (root->_right == nullptr) root = root->_left;
		//左右都不为空
		else
		{
			Node* leftMax = root;
			while (leftMax->_right)
			{
				leftMax = leftMax->_right;
			}
			swap(leftMax->_key, root->_key);
			return _EraseR(root->_left, key);
		}

		delete del; return true;
	}
}
  • destory
cpp 复制代码
void Destory(Node*& root)
{
	if (root == nullptr) return;

	Destory(root->_left);
	Destory(root->_right);
	delete root;
	root = nullptr;
}
  • Copy
cpp 复制代码
Node* Copy(Node* root)
{
	if (root == nullptr) return nullptr;

	Node* croot = new Node(root->_key);
	croot->_left = Copy(root->_left);
	croot->_right = Copy(root->_right);
	return croot;
}

二叉搜索树的应用

K(搜索)模型:
  • K模型即只有key作为关键词,结构中只需储存Key,关键码即为搜索的值
  • 场景:快速判断在不在,门禁
KV(搜索)模型:
  • 每一个关键码Key,与之对应的值Value,即<Key,Value>的键值对
  • 例如统计单词出现的个数,通过一个值找另外一个值,
相关推荐
南境十里·墨染春水1 分钟前
C++笔记 STL——set
开发语言·c++·笔记
dgaf14 分钟前
DX12 快速教程(17) —— 立体图标与合并渲染
c语言·c++·3d·图形渲染·d3d12
一个爱编程的人3 小时前
一个数是不是素数
数据结构·算法
charlie1145141913 小时前
通用GUI编程技术——图形渲染实战(三十八)——顶点缓冲与输入布局:GPU的第一个三角形
开发语言·c++·学习·图形渲染·win32
用户805533698033 小时前
现代Qt开发教程(新手篇)1.10——进程
c++·qt
忡黑梨3 小时前
eNSP_从直连到BGP全网互通
c语言·网络·数据结构·python·算法·网络安全
海参崴-3 小时前
C++ STL篇 AVL树的模拟实现
开发语言·c++
汉克老师3 小时前
GESP2025年6月认证C++五级( 第二部分判断题(1-10))
c++·贪心算法·分治算法·线性筛法·gesp5级·gesp五级
6Hzlia3 小时前
【Hot 100 刷题计划】 LeetCode 15. 三数之和 | C++ 排序+双指针
c++·算法·leetcode
vegetablesssss3 小时前
VTK切割图
c++·qt·vtk