c++ 搜索二叉树——主要包括:《搜索二叉树的概念》《增删查的分析和解题思路》《完整实现代码》《搜索二叉树的性能分析》

经过我们上一篇博客的书写,我们可以了解到 map / multimap / set / multiset底层使用搜索二叉树实现的,那么搜索二叉树又是什么呢?下面我们就走进搜索二叉树的世界了解一下。

《一》搜索二叉树的概念
二叉搜索树又称二叉排序树,它可能是一个空树,也有可能具有以下性质的二叉树:

  1. 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
  2. .若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
  3. .它的左右子树也分别为二叉搜索树
    下面,我就用图形试一试
    c++ 搜索二叉树——主要包括:《搜索二叉树的概念》《增删查的分析和解题思路》《完整实现代码》《搜索二叉树的性能分析》_第1张图片
    = {5,3,4,1,7,8,2,6,0,9};

这就是基础的搜索二叉树的树状图

《二》增,删,查,找

在用代码实现之前,我们再了解一下,它的查找,

c++ 搜索二叉树——主要包括:《搜索二叉树的概念》《增删查的分析和解题思路》《完整实现代码》《搜索二叉树的性能分析》_第2张图片
下面我们再看一下插入的过程分析
c++ 搜索二叉树——主要包括:《搜索二叉树的概念》《增删查的分析和解题思路》《完整实现代码》《搜索二叉树的性能分析》_第3张图片
最后,我们在看一下删除的过程分析:
c++ 搜索二叉树——主要包括:《搜索二叉树的概念》《增删查的分析和解题思路》《完整实现代码》《搜索二叉树的性能分析》_第4张图片

看了这几个分析之后,我们接下来就要实现完成搜索二叉树的实现了。

#pragma once
#include
using namespace std;

template
struct BSTreeNode
{
	BSTreeNode* _left;
	BSTreeNode* _right;
	K _key;

	BSTreeNode(const K& key)
		:_left(nullptr)
		, _right(nullptr)
		, _key(key)
	{}
};

template
class BSTree //Binary search tree
{
	typedef BSTreeNode Node;
public:
	BSTree()
		:_root(nullptr)
	{}

	~BSTree()
	{}

	bool Insert(const K& key)
	{
		if (_root == nullptr)
		{
			_root = new Node(key);
			return true;
		}
		Node* parent = nullptr;
		Node* cur = _root;
		while (cur)
		{
			if (cur->_key < key)
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (cur->_key > key)
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				return false;
			}
		}

		cur = new Node(key);
		if (parent->_key  < key)
		{
			parent->_right  = cur;
		}
		else
		{
			parent->_left = cur;
		}

		return true;
	}

	Node* Find(const K& key)
	{
		Node*cur = _root;
		while (cur)
		{
			if (cur->_key > key)
			{
				cur = cur->_left;
			}
			else if (cur->_key < key)
			{
				cur = cur->_right;
			}
			else
			{
				return cur;
			}
		}
	}

	bool Erase(const K& key)
	{
		Node* parent = nullptr;
		Node* cur = _root;
		while (cur)
		{
			if (cur->_key > key)
			{
				parent = cur;
				cur = cur->_left;
			}
			else if (cur->_key < key)
			{
				parent = cur;
				cur = cur->_right;
			}
			else
			{
				//1.节点为空,父亲指向节点的右,删除节点
				//2.节点右为空,父亲指向节点的左,删除节点
				//3.节点的左右都不为空,找右数最左节点,或者左数最右节点
				Node* del = cur;
				if (cur->_left == nullptr)
				{
					if (parent == nullptr)
					{
						_root = cur->_right;
					}
					else
					{
						if (parent->_left == cur)
						{
							parent->_left = cur->_right;
						}
						else
						{
							parent->_right = cur->_right;
						}
					}
				}
				else if (cur->_right == nullptr)
				{
					if (parent == nullptr)
					{
						_root = _root->_left;
					}
					else
					{
						if (cur == parent->_left)
						{
							parent->_left = cur->_left;
						}
						else
						{
							parent->_right = cur->_left;
						}
					}
				}
				else
				{
					//Node* p_replace = nullptr;//这里一定不会为空,因为他不会是根;
					Node* p_replace = cur; 
					Node* replace = cur->_right;

					while (replace->_left)
					{
						p_replace = replace;
						replace = replace->_left;
					}
					cur->_key = replace->_key;
					//删除replace节点
					if (p_replace->_left == replace)
					{
						p_replace->_left = replace->_right;
					}
					else
					{
						p_replace->_right = replace->_right;
					}

					del = replace;
				}
				delete del;
				return true;
			}
		}
		return false;
	}
	void _InOrder(Node* root)
	{
		if (root == nullptr)
			return;

		_InOrder(root->_left);
		cout << root->_key <<" ";
		_InOrder(root->_right);
	}

	void InOrder()
	{
		_InOrder(_root);
		cout << endl;
	}
private:
	Node* _root;
};

int TestBSTree()
{
	/*BSTree t;
	t.Insert(3);
	t.Insert(2);
	t.Insert(4);
	t.Insert(6);
	t.Insert(5);
	t.Insert(1);

	t.InOrder();

	t.Erase(5);*/

	BSTree t;

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

	t.Erase(2);
	t.InOrder();

	t.Erase(8);
	t.Erase(1);
	t.Erase(5);

	t.InOrder();

	for (auto e : a)
	{
		t.Erase(e);
	}
	t.InOrder();
	return 0;
}

我们再看一下实现的调用接口,就非常简单了:

int main()
{
     TestBSTree();
      return 0;
}

下面,我们就是执行以下程序,来看一下他的结果。
c++ 搜索二叉树——主要包括:《搜索二叉树的概念》《增删查的分析和解题思路》《完整实现代码》《搜索二叉树的性能分析》_第5张图片

下面,我们还要看一下,它的性能分析。
《四》搜索二叉树的性能分析

  1. 删除和增加都是在查找的基础上实现的,所以查找的效率,代表了搜索二叉树的各个性能。
  2. 对有n个结点的二叉搜索树,若每个元素查找的概率相等,则二叉树搜索平均查找长度是结点在二叉搜索树的深度的函数,即结点越深,则比较次数越多。
  3. 下面我们看一张图片来分析。

c++ 搜索二叉树——主要包括:《搜索二叉树的概念》《增删查的分析和解题思路》《完整实现代码》《搜索二叉树的性能分析》_第6张图片
上面的:《 有单支 》—》》其实为《《—《 右单只 》

最优的情况:搜索二叉树为完全二叉树,其平均比较次数为:log2 N;
最坏的情况:搜索二叉树为单支结构,其平均比较次数为:frac{N}{2};

问题:如果退化成单支树,二叉搜索树的性能就失去了。那能否进行改进,不论按照什么次序插入关键码,都可以是二叉搜索树的性能最佳?
下面我们就要实现以下那些优化的树了,我会把实现的链接放到下面的,

这就是我们实现的搜索二叉树的思想和实现代码,可以借鉴一下,有什么问题,可以在下面的评论区,询问我。

你可能感兴趣的:(c++的进程)