二叉搜索树

概念

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

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

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

  • 解决了数组插入删除数据时的效率问题,并且衍生出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>的键值对
  • 例如统计单词出现的个数,通过一个值找另外一个值,
相关推荐
安全二次方security²2 小时前
CUDA C++编程指南(7.2)——C++语言扩展之变量内存空间指定符
c++·人工智能·nvidia·cuda·内存空间指定符·__shared__·__device__
近津薪荼2 小时前
优选算法——双指针1(数组分块)
c++·学习·算法
Дерек的学习记录2 小时前
二叉树(下)
c语言·开发语言·数据结构·学习·算法·链表
气派飞鹰2 小时前
windows下C++个人开发最佳实践(CMake+vcpkg+trae)
开发语言·c++·个人开发
冷崖2 小时前
桥模式-结构型
c++·设计模式
D_evil__2 小时前
【Effective Modern C++】第三章 转向现代C++:9. 优先选用别名声明,而非typedef
c++
leaves falling2 小时前
c语言- 有序序列合并
c语言·开发语言·数据结构
HellowAmy2 小时前
我的C++规范 - 回调的设想
开发语言·c++·代码规范
代码无bug抓狂人2 小时前
前缀和算法和单调队列算法(经典例题)
数据结构·算法