1.二叉搜索树概念
二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:
若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
它的左右子树也分别为二叉搜索树
2.insert和find和InOrder实现
就讲一下insert怎么实现,分为二种情况,一种是二叉树为空,另一种不为空插入,第一种很好解决,第二种,因为要满足,搜索二叉树的要左子树要比跟小,右子树要比跟大,那么我们只要用插入的数和根比大小就好了,根小于插入的数就访问右边,根大于插入的数就访问左边,一直循环找到空节点为止,最后就是找到位置插入了,但是要插入的位置是左边还是右边不清楚,那么很简单记录这个节点的父亲节点再比较大小,比父亲节点小左边,比父亲节点大右边。
find这个也简单其实和insert一样访问到空节点就代表没找到,而找到了的情况是循环里面要查找的数,不小于或者大于根的左右树
#pragma once
template<class K>
struct BSTreeNode
{
BSTreeNode<K>* _left;
BSTreeNode<K>* _right;
K _key;
BSTreeNode(const K& key)
:_left(nullptr)
, _right(nullptr)
, _key(key)
{
}
};
template<class K>
class BSTree
{
typedef BSTreeNode<K> Node;
public:
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;
}
}
return false;
}
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;
}
void InOrder()
{
_InOrder(_root);
}
private:
void _InOrder(Node* root)
{
if (root == nullptr)
return;
_InOrder(root->_left);
cout << root->_key << " ";
_InOrder(root->_right);
}
Node* _root=nullptr;
};
void TestBSTree()
{
BSTree<int> t;
int a[] = {
8, 3, 1, 10, 6, 4, 7, 14, 13 };
for (auto e : a)
{
t.insert(e);
}
t.InOrder();
t.insert(16);
t.insert(9);
t.InOrder();
}
运行结果
3.erase实现
想删除肯定先遍历,删完分为
a. 要删除的结点无孩子结点
b. 要删除的结点只有一个孩子,左为空或右为空
d. 要删除的结点有左、右孩子结点
等情况来实现
只有一个孩子的情况下:要考虑要删除的节点是left还是right为空,并且还要考虑,可能是只有根左子树没有右子树的情况,或者是根右子树没有左子树的情况,毕竟原理是删除cur,让父亲节点的左边或者右边指向要删除节点的左边或者右边
有左右节点:让删除的节点和要删除节点的right中最小交换,或者覆盖,再把要删除的节点删除
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
{
// 一个孩子--左为空 or 右为空
// 两个孩子 -- 替换法
if (cur->_left == nullptr)
{
//if(cur==nullptr)
if (cur == _root)//没有左子树问题
{
_root = cur->_right;
}
else
{
if (cur == parent->_left)
{
parent->_left = cur->_right;