目录
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),这就需要引入平衡二叉树或红黑树来限制其高度,从而提高性能。