namespace k
{
template<class K>
struct TreeNode
{
TreeNode(K key)
:left(nullptr), right(nullptr),_key(key)
{}
TreeNode<K>* left;
TreeNode<K>* right;
K _key;
};
template<class K>
class BsTree
{
public:
typedef TreeNode<K> Node;
bool Insert(const K& key)//插入
{
if (_root == nullptr)
{
_root = new Node(key);
return true;
}
Node* cur = _root;
Node* prt = nullptr;
//用一个prt变量记录插入位置的父亲节点
while (cur)
{
if (cur->_key < key)
{
prt = cur;
cur = cur->right;
}
else if (cur->_key > key)
{
prt = cur;
cur = cur->left;
}
else
{
return false;
}
}
cur = new Node(key);
//让父亲节点指向新插入的节点
if (prt->_key < key)
{
prt->right = cur;
}
else
{
prt->left = cur;
}
return true;
}
bool Find(const K& key)
{
Node* cur = _root;
while (cur)
{
if (key > cur->_key)
{
cur = cur->right;
}
else if (key < cur->_key)
{
cur = cur->left;
}
else
{
return true;
}
}
return false;
}
bool Erase(const K& key)
{
//需要一个prt节点保存删除元素的父亲节点,用于后续连接
Node* prt = nullptr;
Node* cur = _root;
while (cur)
{
if (cur->_key < key)
{
prt = cur;
cur = cur->right;
}
else if (cur->_key > key)
{
prt = cur;
cur = cur->left;
}
else//找到了,开始删除
{
//左为空,则父亲指向右
if (cur->left == nullptr)
{
//如果cur为根节点,让根节点等于右
if (cur == _root)
{
_root = cur->right;
}
else
{
if (cur == prt->left)
{
prt->left = cur->right;//cur为父亲的左则让父亲的左指向右
}
else
{
prt->right = cur->right;//cur为父亲的右则让父亲的右指向右
}
}
delete cur;
}//右为空,则父亲指向左,具体做法与上类似
else if (cur->right == nullptr)
{
if (cur == _root)
{
_root = cur->left;
}
else
{
if (cur == prt->left)
{
prt->left = cur->left;
}
else
{
prt->right = cur->left;
}
}
delete cur;
}
else//cur的两边都不为空
{
Node* RightMinPrt = cur;
Node* RightMin = cur->right;
//寻找cur的右树中最小值,并记录最小值的父亲。
while (RightMin->left)
{
RightMinPrt = RightMin;
RightMin = RightMin->left;
}
cur->_key = RightMin->_key;
if (RightMin == RightMinPrt->right)//最小值为最小值父亲的右节点
{
RightMinPrt->right = RightMin->right;
}
else//最小值为最小值父亲的左节点
RightMinPrt->left = RightMin->right;
delete RightMin;
}
return true;
}
}
return false;
}
void _Inorder(Node* N)
{
if (N == nullptr)
{
return;
}
_Inorder(N->left);
cout << N->_key << " ";
_Inorder(N->right);
}
//打印这棵树
void Inorder()
{
_Inorder(_root);
cout << endl;
}
private:
Node* _root = nullptr;
};
}
运行一下。
int main()
{
k::BsTree<int> t;
int arr[] = { 5,3,4,1,7,8,2,6,0,9 };
for (auto e : arr)
{
t.Insert(e);
}
t.Inorder();
for (auto e : arr)
{
t.Erase(e);
t.Inorder();
}
return 0;
}
以上是一个key模型,下面还有一个key value模型的实现
namespace k
{
template<class K, class V>
struct TreeNode
{
TreeNode(const K& key, const V& value)
:left(nullptr), right(nullptr),_key(key), _value(value)
{}
TreeNode<K, V>* left;
TreeNode<K, V>* right;
K _key;
V _value;
};
template<class K, class V>
class BsTree
{
public:
typedef TreeNode<K, V> Node;
bool Insert(const K& key, const V& value)//插入
{
if (_root == nullptr)
{
_root = new Node(key, value);
return true;
}
Node* cur = _root;
Node* prt = nullptr;
//用一个prt变量记录插入位置的父亲节点
while (cur)
{
if (cur->_key < key)
{
prt = cur;
cur = cur->right;
}
else if (cur->_key > key)
{
prt = cur;
cur = cur->left;
}
else
{
return false;
}
}
cur = new Node(key, value);
//让父亲节点指向新插入的节点
if (prt->_key < key)
{
prt->right = cur;
}
else
{
prt->left = cur;
}
return true;
}
Node* Find(const K& key)
{
Node* cur = _root;
while (cur)
{
if (key > cur->_key)
{
cur = cur->right;
}
else if (key < cur->_key)
{
cur = cur->left;
}
else
{
return cur;
}
}
return nullptr;
}
bool Erase(const K& key)
{
//需要一个prt节点保存删除元素的父亲节点,用于后续连接
Node* prt = nullptr;
Node* cur = _root;
while (cur)
{
if (cur->_key < key)
{
prt = cur;
cur = cur->right;
}
else if (cur->_key > key)
{
prt = cur;
cur = cur->left;
}
else//找到了,开始删除
{
//左为空,则父亲指向右
if (cur->left == nullptr)
{
//如果cur为根节点,让根节点等于右
if (cur == _root)
{
_root = cur->right;
}
else
{
if (cur == prt->left)
{
prt->left = cur->right;//cur为父亲的左则让父亲的左指向右
}
else
{
prt->right = cur->right;//cur为父亲的右则让父亲的右指向右
}
}
delete cur;
}//右为空,则父亲指向左,具体做法与上类似
else if (cur->right == nullptr)
{
if (cur == _root)
{
_root = cur->left;
}
else
{
if (cur == prt->left)
{
prt->left = cur->left;
}
else
{
prt->right = cur->left;
}
}
delete cur;
}
else//cur的两边都不为空
{
Node* RightMinPrt = cur;
Node* RightMin = cur->right;
//寻找cur的右树中最小值,并记录最小值的父亲。
while (RightMin->left)
{
RightMinPrt = RightMin;
RightMin = RightMin->left;
}
cur->_key = RightMin->_key;
if (RightMin == RightMinPrt->right)//最小值为最小值父亲的右节点
{
RightMinPrt->right = RightMin->right;
}
else//最小值为最小值父亲的左节点
RightMinPrt->left = RightMin->right;
delete RightMin;
}
return true;
}
}
return false;
}
void _Inorder(Node* N)
{
if (N == nullptr)
{
return;
}
_Inorder(N->left);
cout << N->_key << " ";
_Inorder(N->right);
}
//打印这棵树
void Inorder()
{
_Inorder(_root);
cout << endl;
}
private:
Node* _root = nullptr;
};
}
二叉搜索树在插入数据有序的情况下,访问效率是O(N),效率不够好。解决方法为设计成红黑树或者AVL树。