文章目录
–
1、构建一个二叉搜索树节点
template<class K>
//struct BinarySearchTreeNode
struct BSTreeNode//二叉搜索树
{
BSTreeNode<K>* _left;
BSTreeNode<K>* _right;
K _key;
BSTreeNode(const K& key)
:_left(nullptr)
, _right(nullptr)
, _key(key)
{}
};
2、构建一个搜索树的类
template<class K>
class BSTree
{
typedef BSTreeNode<K> Node;
public:
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;
}
bool Find(const K& key)
{
Node* cur = root;
while (cur)
{
if (cur->_key < key)
{
cur = cur->_right;
}
else if (cur->_key > key)
{
cur = cur->_left;
}
else
{
return true;
}
}
}
void InOrder()//不至于用友元,但是不想用get,可以套一层
{//因为在外部访问不到私有的_root
_InOrder(_root);
}
private:
void _InOrder(Node* root)
{
if (root == nullptr)
{
return;
}
_InOrder(root->_left);
cout << root->_key << " ";
_InOrder(root->_right);
}
private:
Node* _root = nullptr;
};
3、查找一个二叉搜索树节点
bool Find(const K& key)
{
Node* cur = _root;
while (cur)
{
if (cur->_key < key)
{
cur = cur->_right;
}
else if (cur->_key > key)
{
cur = cur->_left;
}
else
{
return true;
}
}
}
4、删除一个二叉树节点(考虑节点在叶子,或者根)
先看图片 —删除节点左为空,让父亲指向我的右,删除节点右为空,让父亲指向我的左 , 如果根为空,则更新
bool Erase(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
{
// 删除节点 //左为空,父亲指向我的右
if (cur->_left == nullptr)
{
//if(parent == nullptr)
if (cur == _root)//如果删除的是根
{
_root = cur->_right;//因为左为空所以更新右
}
else
{
if (cur == parent->_left)
{
parent->_left = cur->_right;
}
else
{
parent->_right = cur->_right;
}
}
delete cur;
}
else if (cur->_right == nullptr)
{
//if(parent == nullptr)
if (cur == _root)//如果删除的是根
{
_root = cur->_left;//因为右为空所以更新左
}
else
{
if (cur == parent->_left)
{
parent->_left = cur->_left;
}
else
{
parent->_right = cur->_left;
}
}
//右为空,父亲指向我的左
delete cur;
}
5、删除一个二叉树节点(考虑节点左右都不为空)
第一种情况删除的不是根, 第二种情况删除根需要额外判断
else
{//左右都不为空,替换法删除
//查找右子树的最左节点替换删除
Node* rightMinParent = cur;
Node* rightMin = cur->_right;
while (rightMin->_left)
{
rightMinParent = rightMin;
rightMin = rightMin->_left;
}
swap(cur->_key, rightMin->_key);
if (rightMinParent->_left == rightMin)
rightMinParent->_left = rightMin->_right;
else
rightMinParent->_right = rightMin->_right;
delete rightMin;
}
return true;
}
}
return false; // 此处应该是返回false,表示未找到要删除的节点
}
6、两个部分组合起来一个完整的删除接口
bool Erase(const K& key)
{
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
{
// 删除节点 //左为空,父亲指向我的右
if (cur->_left == nullptr)
{
//if(parent == nullptr)
if (cur == _root)
{
_root = cur->_right;
}
else
{
if (cur == parent->_left)
{
parent->_left = cur->_right;
}
else
{
parent->_right = cur->_right;
}
}
delete cur;
}
else if (cur->_right == nullptr)
{
//if(parent == nullptr)
if (cur == _root)
{
_root = cur->_left;
}
else
{
if (cur == parent->_left)
{
parent->_left = cur->_left;
}
else
{
parent->_right = cur->_left;
}
}
//右为空,父亲指向我的左
delete cur;
}
else
{//左右都不为空,替换法删除
//查找右子树的最左节点替换删除
Node* rightMinParent = cur;
Node* rightMin = cur->_right;
while (rightMin->_left)
{
rightMinParent = rightMin;
rightMin = rightMin->_left;
}
swap(cur->_key, rightMin->_key);
if (rightMinParent->_left == rightMin)
rightMinParent->_left = rightMin->_right;
else
rightMinParent->_right = rightMin->_right;
delete rightMin;
}
return true;
}
}
return false; // 此处应该是返回false,表示未找到要删除的节点
}
7、测试
private://.头文件
Node* _root = nullptr;
};
void TestBSTree1()
{
int a[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };
BSTree<int> t1;
for (auto e : a)
{
t1.Insert(e);
}
t1.InOrder();
}
//.cpp源文件
#include<iostream>
using namespace std;
#include"BinarySearchTree.h"
int main()
{
TestBSTree1();
return 0;
}
在这个地方我们可以看到已经按我们预期边插入边排序排好了序