目录
二叉搜索树的性质:
若其左子树非空,则左子树上所有节点的值都小于根节点的值
若其右子树非空,则右子树上所有节点的值都大于根节点的值
其左右子树都是一棵二叉查找树
结构
#include<iostream>
#include<string>
using namespace std;
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 //Binary Search Tree
{
typedef BSTreeNode<K> Node;
public:
private:
Node* _root=nullptr;
};
插入元素
因为是搜索树,根据它的性质可知,左孩子永远比父亲结点小,右孩子永远比父亲结点大
我们定义两点指针,分别指向孩子结点和父亲结点,先找到需要插入的位置,在判断插入的孩子结点是父亲结点的左孩子或右孩子
例:我们已经有5,3,4 我们在插入1
代码实现:
bool Insrt(const K& key)
{
//如果没有结点就创建一个结点
if (_root == nullptr) {
_root = new Node(key);
return true;
}
Node* cur = _root;
Node* parent = nullptr;
//找到需要插入点位置
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;
}
}
return false;
}
遍历元素:
根据二叉查找树的特性:二叉排序树通过中序遍历可以得到递增序列
//中序遍历
void _InOrder(Node* root)
{
if (root == nullptr)
return;
_InOrder(root->_left);
cout << root->_key << " ";
_InOrder(root->_right);
}
void InOrder() //向类外提供的接口
{
_InOrder(_root);
cout << endl;
}
元素的删除
1、定义两个指针,分别指向当前位置结点和当前位置的父亲结点,从根结点往下找,找到需要删除的结点
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)
{
}
//右为空
else if (cur->_right == nullptr)
{
}
//左右都不为空
else
{
}
return true;
}
}
return false;
}
2、分情况讨论,如果他的左为空 ,或者右为空,或者左右都不为空
1>左为空,
如果是左为空,且当前结点(cur)是父亲结点(parent)的右结点,那么就将父亲(parent)的右指向当前位置(cur)的右
如果是左为空,且当前结点(cur)是父亲结点(parent)的左结点,那么就将父亲(parent)的左指向当前位置(cur)的右
if (cur->_left == nullptr)
{
if (cur == _root)
{
_root = cur->_left;
}
else
{
//判断cur是parent的左子树还是右子树
if (parent->_right == cur) //cur是parent的右子树
{
parent->_right = cur->_right;
}
else //cur是parent的左子树
{
parent->_left = cur->_right;
}
}
delete cur;
}
2>右为空
如果是右为空,且当前结点(cur)是父亲结点(parent)的左结点,那么就将父亲(parent)的左指向当前位置(cur)的左
如果是左为空,且当前结点(cur)是父亲结点(parent)的右结点,那么就将父亲(parent)的右指向当前位置(cur)的左
else if (cur->_right == nullptr)
{
if (cur == _root)
_root = cur->_left;
}
else
{
if (parent->_left == cur)
{
parent->_left = cur->_left;
}
else
{
parent->_right = cur->_left;
}
}
delete cur;
}
3>左右都不为空
左右都不为空的情况下,定义三个指针,分别指向需要删除的结点(cur),以cur的右孩子的最小结点(rightMin),ringhtMin的父亲结点(rightMinParent)
先将rightMin结点的值个复给cur,在删除rightMin结点
{
Node* rightMinParent = cur
Node* rightMin = cur->_right; //用右侧的最小节点来替
//找到右侧最小节点
while (rightMin->_left)
{
rightMinParent = rightMin;
rightMin = rightMin->_left;
}
cur->_key = rightMin->_key;
//转换成删除rightMin
if (rightMin == rightMinParent->_left)
rightMinParent->_left = rightMin->_right;
else
rightMinParent->_right = rightMin->_right;
delete rightMin;
}
全部代码
#include<iostream>
#include<string>
using namespace std;
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 //Binary Search Tree
{
typedef BSTreeNode<K> Node;
public:
bool Insrt(const K& key)
{
if (_root == nullptr)
{
_root = new Node(key);
return true;
}
Node* cur = _root;
Node* parent = nullptr;
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 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 (cur == _root)
{
_root = cur->_left;
}
else
{
if (parent->_right == cur)
{
parent->_right = cur->_right;
}
else
{
parent->_left = cur->_right;
}
}
delete cur;
}
else if (cur->_right == nullptr)
{
if (cur == _root)
{
_root = cur->_left;
}
else
{
if (parent->_left == cur)
{
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;
}
cur->_key = rightMin->_key;
if (rightMin == rightMinParent->_left)
rightMinParent->_left = rightMin->_right;
else
rightMinParent->_right = rightMin->_right;
delete rightMin;
}
return true;
}
}
return false;
}
本篇就分享到这里,如果本文对您有帮助请点赞支持一下~
文章尚有不足,欢迎大牛指正.