学习->C++篇十三:二叉搜索树

目录

1.概述

2.实现

3.性能分析


1.概述

二叉搜索树又称二叉排序树,它满足如下性质:

1.空树也是二叉排序树。

2.若左子树不为空,则左子树的节点的值都小于根节点的值。

3.若右子树不为空,则右子树的节点的值都大于根节点的值。

4.左右子树也都是二叉搜索树。

二叉搜索树有两种模型:

Key模型:只存储key,也作为搜索的值。

Key和Value的模型:存储key和value的键值对,每个key都对应一个value。

2.实现

根据性质,可实现二叉搜索树的Key模型(不允许重复键)如下:

#pragma once
#include<iostream>
#include"BSTree.h"
using std::cout;
using std::cin;
using std::endl;

template<class T>
struct BSTreeNode
{
	BSTreeNode(const T&data)
		:_pleft(nullptr)
		,_pright(nullptr)
		,_data(data)
	{}
	BSTreeNode<T>* _pleft;
	BSTreeNode<T>* _pright;
	T _data;
};

template<class T>
class BSTree
{

public:
	typedef BSTreeNode<T> Node;

	BSTree():_root(nullptr) {}
	void clear() { _clear(_root); _root = nullptr; }
	~BSTree() { clear(); }

	Node* Find(const T& data)
	{
		Node* cur = _root;
		while(cur)
		{
			if (cur->_data < data)
				cur = cur->_pright;
			else if (cur->_data > data)
				cur = cur->_pleft;
			else
				return cur;
		}
		return cur;
	}	

	bool Insert(const T& data)
	{
		if (_root == nullptr)
		{
			_root = new Node(data);
			return true;
		}

		Node* prev = nullptr;
		Node* cur = _root;
		while (cur)
		{
			prev = cur;
			if (cur->_data < data)
				cur = cur->_pright;
			else if (cur->_data > data)
				cur = cur->_pleft;
			else
				return false;
		}

		Node* newnode = new Node(data);
		if (prev->_data > data)
			prev->_pleft = newnode;
		else
			prev->_pright = newnode;
		return true;
	}

	bool Erase(const T& data)
	{
		Node* parent = nullptr;
		Node* cur = _root;
		while (cur)
		{
			if (cur->_data == data)
			{
		        //三种情况
				if (cur->_pleft == nullptr)//(1)左子树为nullptr
				{
					if (cur == _root)//要删除的节点为root
						_root = cur->_pright;
					else if (parent->_pleft == cur)
						parent->_pleft = cur->_pright;
					else
						parent->_pright = cur->_pright;
					delete cur;
				}
				else if (cur->_pright == nullptr)//(2)右子树为nullptr
				{
					if (cur == _root)//要删除的节点为root
						_root = cur->_pleft;
					else if (parent->_pleft == cur)
						parent->_pleft = cur->_pleft;
					else
						parent->_pright = cur->_pleft;
					delete cur;
				}
				else//(3)左右子树都不为nullptr,替代法删除(可选右子树的最左节点)
				{
					Node* minParent = cur;
					Node* minRight = cur->_pright;
					while (minRight->_pleft)
					{
						minParent = minRight;
						minRight = minRight->_pleft;
					}
					std::swap(minRight->_data, cur->_data);
					if (minRight == cur)
						cur->_pright = minRight->_pright;
					else
						minParent->_pleft = minRight->_pright;
					delete minRight;
				}
				return true;
			}
			else if (cur->_data < data)
			{
				parent = cur;
				cur = cur->_pright;
			}
			else
			{
				parent = cur;
				cur = cur->_pleft;
			}
		}
		return false;
	}

	void Inorder()
	{
		_Inorder(_root);
		cout << endl;
	}
private:
	void _Inorder(Node* root)
	{
		if (root)
		{
			_Inorder(root->_pleft);
			cout << root->_data << " ";
			_Inorder(root->_pright);
		}
	}
	void _clear(Node* root)
	{
		if (root)
		{
			_clear(root->_pleft);
			_clear(root->_pright);
			delete root;
		}
	}
private:
	Node* _root;
};

测试代码:

#include<iostream>
#include"BSTree.h"
using std::cout;
using std::cin;
using std::endl;

int main() 
{
	BSTree<int>bstree;
	bstree.Insert(72);
	bstree.Insert(213);
	bstree.Insert(123);
	bstree.Insert(2);
	bstree.Insert(7);
	bstree.Insert(6);

	bstree.Inorder();
	bstree.Erase(72);
	bstree.Erase(7);
	bstree.Erase(123);
	bstree.Inorder();
	return 0;
}

输出:


3.性能分析

        二叉搜索树的插入和删除都需要经过一番查找,查找到对应节点的效率大大影响即其的效率。在树接近满二叉树时,树的节点个数为N,则高度接近logN,则查找效率为O(logN),是这棵树较优的情况,但当这颗树退化成单支等情况时,在最坏的情况下查找效率为O(N)左右,效率较低,为解决效率问题,可以引入平衡规则将树的子树高度差进行限制,从而让最坏的情况的查找效率也为log(N),这就需要引入平衡二叉树或红黑树来限制其高度,从而提高性能。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值