C++-二叉搜索树的查找&插入&删除-二叉搜索树代码实现-二叉搜索树性能分析及解决方案

Posted 天津 唐秙

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++-二叉搜索树的查找&插入&删除-二叉搜索树代码实现-二叉搜索树性能分析及解决方案相关的知识,希望对你有一定的参考价值。

1. 二叉搜索树

1.1 概念

  二叉搜索树又叫做二叉排序树或者是一棵空树,具有以下性质:

  • 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值

  • 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值

  • 它的左右子树也是二叉搜索树
    在这里插入图片描述

     int a[] = {5,3,4,1,7,8,2,6,0,9}
    

1.2 二叉搜索树操作

1.2.1 二叉搜索树的查找

思路:

  • 在根不为空的前提下:
  • 如果根节点key == target,返回true
  • 如果根节点key > target,在key的左子树查找
  • 如果根节点key < target,在key的右子树查找
  • 根为空,返回false

实现:

BSTNode<T>* Search(BSTNode<T> *t, const T &key)const
	{
		if (t == nullptr || t->data == key)
			return t;
		if (key < t->data)
			return Search(t->left, key);
		else
			return Search(t->right, key);
	}

1.2.2 二叉搜索树的插入

思路:

  • 如果树为空,直接将插入的数据为root节点
  • 如果树不为空,将插入数据和根节点进行比较
  • 数据大于根节点的值,往树的右边走
  • 数据小于根节点的值,往树的左边走
  • 数据等于根节点的值,返回,插入失败,因为已经存在该数据

实现:

bool Insert(BSTNode<T> *&t, const T &x)
	{
		if (t == nullptr)
		{
			t = new BSTNode<T>(x);
			return true;
		}
		if (x < t->data)
			return Insert(t->left, x);
		else if (x > t->data)
			return Insert(t->right, x);
		return false;
	}

1.2.3 二叉搜索树的删除

思路:

  • 首先查找元素是否存在于二叉搜索树中,如果不存在,则返回
  • 删除的节点存在
  • (1)要删除的节点无孩子节点
  • (2)要删除的节点只有左孩子
  • (3)要删除的节点只有右孩子
  • (4)要删除的节点既有左孩子也有右孩子

实现:

bool Remove(BSTNode<T> *&t, const T &x)
	{
		if (t == nullptr)
			return false;
		if (x < t->data)
			Remove(t->left, x);
		else if (x > t->data)
			Remove(t->right, x);
		else
		{
			BSTNode<T> *q;
			if (t->left == nullptr && t->right == nullptr)
			{
				delete t;
				t = nullptr;
			}
			else if (t->left != nullptr && t->right == nullptr)
			{
				q = t;
				t = t->left;
				delete q;
			}
			else if (t->right != nullptr && t->left == nullptr)
			{
				q = t;
				t = t->right;
				delete q;
			}
			else
			{
				q = t->left;
				while (q->right != nullptr)
					q = q->right;
				t->data = q->data;
				Remove(t->left, q->data);
			}
			return true;
		}
	}

1.3 二叉搜索树的实现

#include <iostream>
#include <vector>
#include <assert.h>

using namespace std;

template<class T>
class BSTree;

template<class T>
class BSTNode
{
	friend class BSTree<T>;
public:
	BSTNode() :data(T()), left(nullptr), right(nullptr)
	{}
	BSTNode(T d, BSTNode<T> *left = nullptr, BSTNode<T> *right = nullptr)
		:data(d), left(left), right(right)
	{}
	~BSTNode()
	{}
private:
	T data;
	BSTNode<T>* left;
	BSTNode<T>* right;
};

template<class T>
class BSTree
{
public:
	BSTree() : root(nullptr)
	{}
	BSTree(vector<T> &v) : root(nullptr)
	{
		for (const auto &e : v)
			Insert(e);
	}

public:
	T& Min()const
	{
		return Min(root);
	}
	T& Max()const
	{
		return Max(root);
	}
	BSTNode<T>* Search(const T &key)const
	{
		return Search(root, key);
	}
	bool Insert(const T &x)
	{
		return Insert(root, x);
	}
	bool Remove(const T &x)
	{
		return Remove(root, x);
	}
	void Sort()const
	{
		Sort(root);
	}
protected:
	T& Max(BSTNode<T> *t)const
	{
		assert(t != nullptr);
		while (t->right != nullptr)
			t = t->right;
		return t->data;
	}
	T& Min(BSTNode<T> *t)const
	{
		assert(t != nullptr);
		while (t->left != nullptr)
			t = t->left;
		return t->data;
	}

	BSTNode<T>* Search(BSTNode<T> *t, const T &key)const
	{
		if (t == nullptr || t->data == key)
			return t;
		if (key < t->data)
			return Search(t->left, key);
		else
			return Search(t->right, key);
	}

	bool Insert(BSTNode<T> *&t, const T &x)
	{
		if (t == nullptr)
		{
			t = new BSTNode<T>(x);
			return true;
		}
		if (x < t->data)
			return Insert(t->left, x);
		else if (x > t->data)
			return Insert(t->right, x);
		return false;
	}

	bool Remove(BSTNode<T> *&t, const T &x)
	{
		if (t == nullptr)
			return false;
		if (x < t->data)
			Remove(t->left, x);
		else if (x > t->data)
			Remove(t->right, x);
		else
		{
			BSTNode<T> *q;
			if (t->left == nullptr && t->right == nullptr)
			{
				delete t;
				t = nullptr;
			}
			else if (t->left != nullptr && t->right == nullptr)
			{
				q = t;
				t = t->left;
				delete q;
			}
			else if (t->right != nullptr && t->left == nullptr)
			{
				q = t;
				t = t->right;
				delete q;
			}
			else
			{
				q = t->left;
				while (q->right != nullptr)
					q = q->right;
				t->data = q->data;
				Remove(t->left, q->data);
			}
			return true;
		}
	}

	void Sort(BSTNode<T> *t)const
	{
		if (t != nullptr)
		{
			Sort(t->left);
			cout << t->data << ' ';
			Sort(t->right);
		}
	}
private:
	BSTNode<T> *root;
};

int main()
{
	vector<int> iv{ 10, 15, 18, 12, 20, 5, 9, 7, 3 };
	BSTree<int> bst(iv);
	bst.Sort();
	bst.Insert(13);
	bst.Remove(18);
	cout << endl;
	bst.Sort();
	cout << endl;

	cout << bst.Max() << endl;
	cout << bst.Min() << endl;
	cout << bst.Search(20) << endl;

	return 0;
}

1.4 二叉搜索树的性能分析

  二叉搜索树的插入和删除都必须优先进行查找,因此查找效率代表了二叉搜索树的各操作的主要性能。我们假设某个元素的查找概率相等,如果二叉搜索树的高度越低,平均的比较次数就越少,但是由于树的插入顺序不一样,最后得到的二叉搜索树的结构也可能不一样,比如:再最优的情况下,二叉搜索树为完全二叉树,其平均比较次数为log2^N,最差情况下,二叉搜索树为单支树,这和顺序查找是一样的,其平均比较次数为N/2,那么,当二叉搜索树变成了单支树,就会失去二叉搜索树的性能,因此提出了平衡二叉搜索树。

以上是关于C++-二叉搜索树的查找&插入&删除-二叉搜索树代码实现-二叉搜索树性能分析及解决方案的主要内容,如果未能解决你的问题,请参考以下文章

二叉搜索树(BinarySearchTree)

二叉搜索树(BinarySearchTree)

使用C在搜索二叉树中查找最长路径

Java数据结构二叉搜索树增插,删,创详解

二叉搜索树的查找删除插入

[C/C++]详解STL容器5--二叉搜索树的介绍及模拟实现