二叉搜索树
二叉树的意义是:任何节点最多只允许有两个子节点。这两个子节点被称为左子节点和右子节点。如果从递归的角度来看二叉树的话,二叉树可以被描述成:一个二叉树如果不为空,那么这棵二叉树便是由一个根节点和左右两棵子树构成;左右子树都可能为空。
所谓的二叉搜索树(binary search tree),在二叉树的基础上又升级了要求,二叉搜索树的节点放置规则是:任何节点的键值一定大于其左子树中每一个节点的键值,且一定小于其右子树中的每一个节点的键值。所以对二叉搜索树来说,从根节点一直往左走,直至无路可走,得到的就是该树的最小元素;从根节点一直往右走,直至无路可走,得到的就是该树的最大元素。
二叉搜索树中元素的插入和移除相对麻烦,原因是不能随意的插入和移除,要保证满足二叉搜索树的节点放置规则。
插入新元素时,从根节点开始,遇到键值较大者就向它的左边走,遇到键值较小的就向它的右边走,一直到尾端,即为插入点。
移除旧节点时,分四种情况,第一种是该节点有左子树也有右子树;第二种是该节点是叶子节点,也就是说该节点无孩子节点;第三种是该节点有左子树无右子树;第四种是该节点无左子树有右子树。在代码实现的时候,只需要分两种情况讨论即可,后三种统一处理,第一种单独处理,不过第一种最后也是转化为后三种进行处理的。
BST树的模拟实现:
template<class Type>
class BST;
template<class Type>
class BSTNode
{
friend class BST<Type>;//声明友元类
public:
BSTNode(Type d = Type(),BSTNode<Type>*left=nullptr,
BSTNode<Type>*right=nullptr)
:data(d),leftchild(left),rightchild(right)
{}
~BSTNode()
{}
private:
Type data;
BSTNode<Type> *leftchild;
BSTNode<Type> *rightchild;
};
template<class Type>
class BST
{
public:
BST():root(nullptr)
{}
~BST()
{
Destroy(root);
}
void Destroy(BSTNode<Type> *&t)
{
if (t != nullptr)
{
Destroy(t->leftchild);
Destroy(t->rightchild);
delete t;//释放t指针
t = nullptr;//将t赋空,预防野指针
}
}
public:
bool Insert(const Type &v)
{
return Insert(root, v);
}
bool Remove(const Type &v)
{
return Remove(root, v);
}
BSTNode<Type>* Find(const Type& key)const//不允许修改
{
return Find(root, key);
}
Type Min()const
{
return Min(root);
}
Type Max()const
{
return Max(root);
}
void SortPrint()const
{
SortPrint(root);
cout << endl;
}
protected:
bool Insert(BSTNode<Type> *&t, const Type &v)
{
//非递归实现
//查找插入位置
BSTNode<Type> *p = t, *pr = nullptr;
while (p != nullptr)
{
if (v == p->data)
return false;
pr = p;
if (v < t->data)
p = p->leftchild;
else
p = p->rightchild;
}
p = new BSTNode<Type>(v);
//建立连接 两种情况:构建新树 插入节点
if (pr == nullptr)
{
t = p;
return true;
}
if (v < pr->data)
pr->leftchild = p;
else
pr->rightchild = p;
return true;
}
bool Remove(BSTNode<Type>*&t, const Type &key)
{
//查找节点
if (t == nullptr)
return false;
if (key < t->data)
Remove(t->leftchild, key);
else if(key > t->data)
Remove(t->rightchild, key);
else
{
//删除节点
if (t->leftchild != nullptr && t->rightchild != nullptr)
{
BSTNode<Type> *p = t->leftchild;
while (p->rightchild != nullptr)
p = p->rightchild;//找到左子树最右的节点代替t
t->data = p->data;
Remove(t->leftchild, p->data);//删除左子树中最右的节点
}
else
{
//最多只有一颗子树 叶节点 左空右不空 右空左不空
BSTNode<Type> *p = t;//t是要删除的节点位置
if (t->leftchild != nullptr)
t = p->leftchild;
else
t = p->rightchild;
delete p;
}
return true;
}
}
void SortPrint(BSTNode<Type> *t)const
{
if (t != nullptr)
{
SortPrint(t->leftchild);
cout << t->data << " ";
SortPrint(t->rightchild);
}
}
Type Min(BSTNode<Type>*t)const
{
//断言树不为空
assert(t != nullptr);
while (t->leftchild != nullptr)
{
t = t->leftchild;
}
return t->data;
}
Type Max(BSTNode<Type>*t)const
{
assert(t != nullptr);
while (t->rightchild != nullptr)
t = t->rightchild;
return t->data;
}
BSTNode<Type>* Find(BSTNode<Type>*t, const Type& key)const
{
if (t == nullptr || t->data == key)
return t;
if (key < t->data)
return Find(t->leftchild, key);
else
return Find(t->rightchild, key);
}
private:
BSTNode<Type> *root;
};
主函数代码测试:
int main()
{
vector<int> v={ 18,14,12,16,15,20 };
BST<int> bst;
for (int i = 0; i < v.size(); ++i)
{
bst.Insert(v[i]);
}
bst.SortPrint();
bst.Remove(1);
bst.SortPrint();
BSTNode<int>* it = bst.Find(20);
cout << bst.Max() << endl;
cout << bst.Min() << endl;
return 0;
}
执行结果:
12 15 14 18 20
12 15 14 18 20
20
12