二叉搜索树

本文介绍了二叉搜索树的基本概念,包括其特性:左子树节点值小于根节点,右子树节点值大于根节点。讨论了查找、插入和删除操作的逻辑,并指出不同插入顺序会影响树的形态。最佳情况下,查找时间复杂度为O(log2N),最差情况为O(N)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二叉搜索树是一种特殊的二叉树,具有以下性质:
1. 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值。
2. 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值。
3. 它的左右子树也分别为二叉搜索树。
空树也是一颗二叉搜索树。二叉搜索树的中序遍历是有序的。

 

二叉搜索树的查找:

从根结点开始查找,若节点为空则返回 false;若不为空:1. 若节点大小小于要查找的节点,则从它右子树去找;2. 若节点大小大于要查找的节点,则从它的左子树去找;3. 若节点大小等于要查找的节点大小,则返回true。

二叉搜索树的插入:

如果为空树,则直接插入。若树不为空,则从根结点开始查找合适的位置进行插入:1. 若节点大小小于插入节点,则从右子树开始插入;2. 若节点大小大于插入节点,则从左子树开始插入;3. 若为空节点,则将节点插入该位置。

二叉搜索树的删除:

首先查找是否存在该节点,不存在返回false。如果存在: 1. 若要删除的节点的左子树为空,删除该结点且使被删除节点的双亲结点指向被删除结点的右孩子结点。2. 若要删除的节点右子树为空,删除该节点且使被删除节点的双亲节点指向被删除节点的左孩子节点。3. 若要删除的节点左右子树都不为空,寻找该节点左子树的最大节点或者右子树的最小节点,将寻找到节点的值赋值给要删除的节点的值,然后删除找到的节点,代替删除。

二叉搜索树的实现:
 

#include<iostream>
using namespace std;

template<class T>
struct BSTNode
{
	BSTNode(const T& value = T()) 
	:left(nullptr), right(nullptr), val(value)
	{
	}
	BSTNode* left;
	BSTNode* right;
	T val;
};

template<class T>
class BSTree
{
public:
	BSTree() :root(nullptr)
	{
	}
	BSTNode<T>* find(const T& value)
	{
		BSTNode<T>* cur = root;
		while (cur)
		{
			if (value > cur->val)
				cur = cur->right;
			else if (value < cur->val)
				cur = cur->left;
			else
				return cur;
		}
		return nullptr;
	}
	bool insert(const T& value)
	{
		if (root == nullptr)
		{
			root = new BSTNode<T>(value);
			return true;
		}
		BSTNode<T>* cur = root;
		BSTNode<T>* parent = nullptr;
		while (cur)
		{
			if (cur->val > value)
			{
				parent = cur;
				cur = cur->left;
			}
			else if (cur->val < value)
			{
				parent = cur;
				cur = cur->right;
			}
			else
			{
				return false;
			}
		}
		cur = new BSTNode<T>(value);
		if (value < parent->val)
		{
			parent->left = cur;
		}
		else
		{
			parent->right = cur;
		}
		return true;
	}
	bool erase(const T& value = T())
	{
		if (nullptr == root)
		{
			return false;
		}
		BSTNode<T>* cur = root;
		BSTNode<T>* parent = nullptr;
		while (cur)
		{
			if (cur->val > value)
			{
				parent = cur;
				cur = cur->left;
			}
			else if (cur->val < value)
			{
				parent = cur;
				cur = cur->right;
			}
			else
			{
				if (cur->left == nullptr)
				{
					if (cur == parent->left)
					{
						parent->left = cur->right;
					}
					else
					{
						parent->right = cur->right;
					}
				}
				else if (cur->right == nullptr)
				{
					if (cur == parent->left)
					{
						parent->left = cur->left;
					}
					else
					{
						parent->right = cur->left;
					}
				}
				else
				{
					BSTNode<T>* min_right = cur->right;
					parent = cur;
					while (min_right->left)
					{
						parent = min_right;
						min_right = min_right->left;
					}
					cur->val = min_right->val;
					if (min_right == parent->left)
					{
						parent->left = min_right->right;
					}
					else
					{
						parent->right = min_right->right;
					}
					delete min_right;
					min_right = nullptr;
				}
                return true;
			}
		}
		return false;
	}
	void inorder()
	{
		_InOrder(root);
		cout << endl;
	}
	~BSTree()
	{
		_Destroy(root);
	}
private:
	BSTNode<T>* root;

	void _InOrder(BSTNode<T>* _root)
	{
		if (_root)
		{
			_InOrder(_root->left);
			cout << _root->val << " ";
			_InOrder(_root->right);
		}
	}
	void _Destroy(BSTNode<T>* &_root)
	{
		if (_root)
		{
			_Destroy(_root->left);
			_Destroy(_root->right);
			_root = nullptr;
		}
	}
};

int main()
{
	BSTree<int> bst;
	bst.insert(6);
	bst.insert(4);
	bst.insert(8);
	bst.insert(3);
	bst.insert(5);
	bst.insert(7);
	bst.insert(9);
	bst.inorder();
	bst.erase(4);
	bst.inorder();
	system("pause");
	return 0;

}

二叉搜索树的性能分析:
对于一个关键码集合,如果插入顺序不同,得到的二叉搜索树也不同。
查找时间复杂度:
1. 最佳的情况下,二叉搜索树为完全二叉树,时间复杂度为 O(log2N)
2. 最差的情况下,二叉搜索树退化为单支树,相当于一个链表,时间复杂度为O(N)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值