二叉搜索树

概念

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

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

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

  • 解决了数组插入删除数据时的效率问题,并且衍生出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>的键值对
  • 例如统计单词出现的个数,通过一个值找另外一个值,
相关推荐
Thera7772 小时前
C++ 高性能时间轮定时器:从单例设计到 Linux timerfd 深度优化
linux·开发语言·c++
罗超驿3 小时前
独立实现双向链表_LinkedList
java·数据结构·链表·linkedlist
君义_noip4 小时前
信息学奥赛一本通 1952:【10NOIP普及组】三国游戏 | 洛谷 P1199 [NOIP 2010 普及组] 三国游戏
c++·信息学奥赛·csp-s
努力也学不会java4 小时前
【缓存算法】一篇文章带你彻底搞懂面试高频题LRU/LFU
java·数据结构·人工智能·算法·缓存·面试
旖-旎4 小时前
二分查找(x的平方根)(4)
c++·算法·二分查找·力扣·双指针
顶点多余5 小时前
使用C/C++语言链接Mysql详解
数据库·c++·mysql
汉克老师5 小时前
GESP2026年3月认证C++四级( 第二部分判断题(1-10))
c++·指针·函数重载·文件操作·数组·gesp4级·gesp四级
khddvbe5 小时前
C++并发编程中的死锁避免
开发语言·c++·算法
菜菜小狗的学习笔记6 小时前
剑指Offer算法题(四)链表
数据结构·算法·链表
We་ct6 小时前
LeetCode 148. 排序链表:归并排序详解
前端·数据结构·算法·leetcode·链表·typescript·排序算法