数据结构进阶:二叉搜索树


前言

本节内容介绍二叉树的升级版-----二叉搜索树。本节内容比较少,却是后面内容的重要铺垫。


一,二叉搜索树的概念

1.1 二叉搜索树的性质

二叉搜索树又称为二叉排序树,它是一颗空树或具有以下性质的二叉树。

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

1.2 二叉搜索树的操作

1. 二叉搜索树的查找

如果根节点不为空:

如果根节点key==查找key 返回true

如果根节点key>查找key 在其左子树查找

如果根节点key<查找key 在其右节点查找

否则 返回false

2.二叉搜索树的插入

a. 树为空,则直接插入

b. 树不空,按二叉搜索树性质查找插入位置,插入新节点

3.二叉搜索树的删除

首先查找元素是否在二叉树中,如果不存在,则返回,否则要删除的结点可能分为下面四种情况:

a.要删除的结点无孩子结点

b.要删除的结点只有左孩子结点

c.要删除的结点只有右孩子结点

d.要删除的结点有左右孩子结点

看起来有四种情况,其实a可以与情况b,c合并起来,因此真正的删除过程如下:

情况b : 删除该结点且使被删除结点的双亲结点指向被删除结点的左孩子结点。

情况c : 删除该结点且使被删除结点的双亲结点指向被删除结点的右孩子结点

情况d:在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除结点中,再来处理该节点的删除问题

1.3 二叉搜索树的实现

#include <iostream>
using namespace std;

template<class T>
struct BSTNode
{
	BSTNode(const T& x = T())
	: left(nullptr)
	, right(nullptr)
	, data(x)
	{}

	BSTNode<T>* left;
	BSTNode<T>* right;
	T data;
};

// 假设:树中节点的值域唯一
template<class T>
class BinarySearchTree
{
	typedef BSTNode<T> Node;
public:
	BinarySearchTree()
		: root(nullptr)
	{}
	~BinarySearchTree()
	{
		Destroy(root);
	}

	bool Insert(const T& data)
	{
		// 1. 空树---
		// 新插入的节点应该是跟节点
		if (nullptr == root)
		{
			root = new Node(data);
			return true;
		}
		// 2. 树非空
		// a. 找待插入节点在树中的位置--->按照二叉搜索树的性质
		Node* cur = root;
		Node* parent = nullptr;
		while (cur)
		{
			parent = cur;
			if (data < cur->data)
				cur = cur->left;
			else if (data > cur->data)
				cur = cur->right;
			else
				return false;
		}

		// 树中不存在值为data的节点
		// b. 插入新节点
		
		cur = new Node(data);
		if (data < parent->data)
			parent->left = cur;
		else
			parent->right = cur;

		return true;
	}

	Node* Find(const T& data)const
	{
		Node* cur = root;
		while (cur)
		{
			if (data == cur->data)
				return cur;
			else if (data < cur->data)
				cur = cur->left;
			else
				cur = cur->right;
		}
		return nullptr;
	}
	bool Erase(const T& data)
	{
		// 1. 先找data是否存在
		Node* cur = root;
		Node* parent = nullptr;
		while (cur)
		{
			parent = cur;
			if (data == cur->data)
				break;
			else if (data < cur->data)
				cur = cur->left;
			else
				cur = cur->right;
		}

		// 值为data的节点不存在
		if (nullptr == cur)
			return false;

		// 2. 找到值为data的节点,即cur--->将该节点删除掉
		// 删除节点并且保存树的关系

		// 有些节点可以直接删除,但是有些节点不能直接删除
		// 需要对cur子树分情况讨论
		// 1. cur是叶子
		// 2. cur只有左孩子
		// 3. cur只有右孩子
		// 4. cur左右孩子均存在
		// 经过图解分析发现:
		// 情况1实际可以和情况2或者情况3合并起来
		if (nullptr == cur->left)
		{
			// 说明cur可能是叶子节点,也可能是只有右孩子
			;
		}
		else if (nullptr == cur->right)
		{
			// 说明cur只有左孩子
		}
		else
		{
			// 说明cur左孩孩子均存在
		}

		return true;
	}

	void InOrder()
	{
		_InOrder(root);
		cout << endl;
	}

private:
	void _InOrder(Node* proot)
	{
		if (proot)
		{
			_InOrder(proot->left);
			cout << proot->data << " ";
			_InOrder(proot->right);
		}
	}

	void Destroy(Node*& proot)
	{
		if (proot)
		{
			Destroy(proot->left);
			Destroy(proot->right);
			delete proot;
			proot = nullptr;
		}
	}

	
private:
	BSTNode<T>* root;
};


void TestBSTree()
{
	BinarySearchTree<int> t;
	int a[] = { 5, 3, 4, 1, 7, 8, 2, 6, 0, 9 };
	for (auto e : a)
		t.Insert(e);

	t.InOrder();
	
	BSTNode<int>* cur = t.Find(9);
	if (cur)
	{
		cout << "9 is in BSTree" << endl;
	}
	else
	{
		cout << "9 is not in BSTree" << endl;
	}

	cur = t.Find(13);
	if (cur)
	{
		cout << "13 is in BSTree" << endl;
	}
	else
	{
		cout << "13 is not in BSTree" << endl;
	}
}

1.4 二叉搜索树的性能分析

最优情况下,二叉搜索树为完全二叉树,其平均比较次数为:log2N

最差情况下,二叉搜索树退化为单支树,其平均比较次数为:N/2

总结

以上是就是本文内容,千里之行始于足下,坚持住兄弟们。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值