序言:
构造一棵二叉排序树的目的并不是为了排序,而是为了提高查找效率、插入和删除关键字的速度,同时二叉搜索树的这种非线性结构也有利于插入和删除的实现。
目录
(一)BST的定义
(二)二叉搜索树操作
1、BST的查找
2、BST的插入
3、BST的删除
(三)二叉排序树的实现(非递归)
1、查找实现
2、插入实现
3、删除实现
(四)二叉排序树的实现(递归)
1、查找操作
2、插入操作
3、删除操作
(五)其他操作
1、析构
2、构造和拷贝构造
3、赋值重载
(六)总结
二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:
我以下图这棵二叉树为例,给大家进行有关二叉树操作的讲解:
思想:
举例:
二叉排序树作为一种动态树表,其特点是树的结构通常不是一次生成的,而是在查找过程中存在关键字值等于给定值的结点时再进行插入的。
插入结点的过程如下:
插入的结点一定是一个新添加且是查找失败时的查找路径上访问的最后一个结点的左孩子或右孩子。
在二叉排序树中删除一个结点时,不能把以该结点为根的子树上的结点都删除,必须先删除结点从存储二叉排序树的链表上摘下,将因删除结点而断开的二叉链表重新链接起来,确保二叉排序树的性质不会丢失。
首先查找元素是否在二叉搜索树中,如果不存在,则返回, 否则要删除的结点可能分下面四种情
况:
看起来有待删除节点有4中情况,实际情况a可以与情况b或者c合并起来,因此真正的删除过程
如下
代码如下:
//查找操作
bool Find(const K& key)
{
Newnode* 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 Newnode(key);
return true;
}
Newnode* parent = nullptr;
Newnode* 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 Newnode(key);
if (parent->_key < key)
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
return true;
}
代码如下:
//删除操作
bool Erase(const K& key)
{
Newnode* parent = nullptr;
Newnode* 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->_right;
}
else
{
if (parent->_left == cur)
{
parent->_left = cur->_right;
}
else
{
parent->_right = 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 {
// 找右树最小节点替代,也可以是左树最大节点替代
Newnode* pminRight = cur;
Newnode* minRight = cur->_right;
while (minRight->_left)
{
pminRight = minRight;
minRight = minRight->_left;
}
cur->_key = minRight->_key;
if (pminRight->_left == minRight) {
pminRight->_left = minRight->_right;
}
else {
pminRight->_right = minRight->_right;
}
delete minRight;
}
return true;
}
}
return false;
}
递归实现都比较容易,只要大家掌握到了思想,我相信实现起来就是很容易的。
//查找操作
bool _FindR(Newnode* root, const K& key)
{
if (root == nullptr)
return false;
if (root->_key == key)
return true;
if (root->_key < key)
return _FindR(root->_right, key);
else
return _FindR(root->_left, key);
}
//插入操作
bool _InsertR(Newnode*& root, const K& key)
{
if (root == nullptr) {
root = new Newnode(key);
//root = new BSTree(key);
return true;
}
if (root->_key < key) {
return _InsertR(root->_right, key);
}
else if (root->_key > key) {
return _InsertR(root->_left, key);
}
else {
return false;
}
}
验证操作:
//删除操作
bool _EraseR(Newnode*& root,const K& key)
{
if (root == nullptr) {
root = new Newnode(key);
return true;
}
if (root->_key < key)
{
return _EraseR(root->_right, key);
}
else if (root->_key > key)
{
return _EraseR(root->_left, key);
}
else
{
Newnode* del = root;
if (root->_left == nullptr)
{
root = root->_right;
}
else if (root->_right == nullptr)
{
root = root->_left;
}
else
{
Newnode* maxleft = root->_left;
while (maxleft->_left)
{
maxleft = maxleft->_right;
}
swap(root->_key, maxleft->_key);
return _EraseR(root->_left, key);
}
delete del;
return true;
}
}
验证操作:
析构同样的使用递归来进行解决(当然也可以使用循环)。具体如下
代码实现:
//销毁操作
void Destroy(Newnode*& root)
{
if (root == nullptr)
return;
Destroy(root->_left);
Destroy(root->_right);
delete root;
root = nullptr;
}
首先如果我想在搜索二叉树的对象进行拷贝构造能够实现吗?具体如下:
【说明】
【注意】
所以此时就需要写一个深拷贝的拷贝构造函数(递归版本)
Newnode* Copy(Newnode* root)
{
if (root == nullptr)
return nullptr;
Newnode* newRoot = new Newnode(root->_key);
newRoot->_left = Copy(root->_left);
newRoot->_right = Copy(root->_right);
return newRoot;
}
此时因为有了拷贝构造,编译器就不会生成默认的构造函数了,就需要我们自己写(C++11提供了一个关键字——default,可以强制编译器生成默认构造)
BinarySearchTree() = default; // 制定强制生成默认构造
此时,它就会走初始列表用缺省值去初始化:
BinarySearchTree& operator=(BinarySearchTree t)
{
swap(_root, t._root);
return *this;
}
代码演示:
【代码总结】
#pragma once
template
struct BSTree
{
BSTree* _left;
BSTree* _right;
K _key;
BSTree(const K& key)
: _left(nullptr)
, _right(nullptr)
, _key(key)
{}
};
template
class BinarySearchTree
{
typedef BSTree Newnode;
public:
BinarySearchTree() = default; // 制定强制生成默认构造
BinarySearchTree& operator=(BinarySearchTree t)
{
swap(_root, t._root);
return *this;
}
BinarySearchTree(const BinarySearchTree& t)
{
_root = Copy(t._root);
}
~BinarySearchTree()
{
Destroy(_root);
}
//插入操作
bool Insert(const K& key)
{
if (_root == nullptr)
{
_root = new Newnode(key);
return true;
}
Newnode* parent = nullptr;
Newnode* 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 Newnode(key);
if (parent->_key < key)
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
return true;
}
//查找操作
bool Find(const K& key)
{
Newnode* 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 Erase(const K& key)
{
Newnode* parent = nullptr;
Newnode* 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->_right;
}
else
{
if (parent->_left == cur)
{
parent->_left = cur->_right;
}
else
{
parent->_right = 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 {
// 找右树最小节点替代,也可以是左树最大节点替代
Newnode* pminRight = cur;
Newnode* minRight = cur->_right;
while (minRight->_left)
{
pminRight = minRight;
minRight = minRight->_left;
}
cur->_key = minRight->_key;
if (pminRight->_left == minRight) {
pminRight->_left = minRight->_right;
}
else {
pminRight->_right = minRight->_right;
}
delete minRight;
}
return true;
}
}
return false;
}
///
// 递归版本
bool FindR(const K& key)
{
return _FindR(_root, key);
}
bool InsertR(const K& key)
{
return _InsertR(_root, key);
}
bool EraseR(const K& key)
{
return _EraseR(_root, key);
}
void InOrder()
{
_Inorder(_root);
cout << endl;
}
protected:
Newnode* Copy(Newnode* root)
{
if (root == nullptr)
return nullptr;
Newnode* newRoot = new Newnode(root->_key);
newRoot->_left = Copy(root->_left);
newRoot->_right = Copy(root->_right);
return newRoot;
}
//销毁操作
void Destroy(Newnode*& root)
{
if (root == nullptr)
return;
Destroy(root->_left);
Destroy(root->_right);
delete root;
root = nullptr;
}
//查找操作
bool _FindR(Newnode* root, const K& key)
{
if (root == nullptr)
return false;
if (root->_key == key)
return true;
if (root->_key < key)
return _FindR(root->_right, key);
else
return _FindR(root->_left, key);
}
//插入操作
bool _InsertR(Newnode*& root, const K& key)
{
if (root == nullptr) {
root = new Newnode(key);
return true;
}
if (root->_key < key) {
return _InsertR(root->_right, key);
}
else if (root->_key > key) {
return _InsertR(root->_left, key);
}
else {
return false;
}
}
//删除操作
bool _EraseR(Newnode*& root, const K& key)
{
if (root == nullptr) {
root = new Newnode(key);
return true;
}
if (root->_key < key)
{
return _EraseR(root->_right, key);
}
else if (root->_key > key)
{
return _EraseR(root->_left, key);
}
else
{
Newnode* del = root;
if (root->_left == nullptr)
{
root = root->_right;
}
else if (root->_right == nullptr)
{
root = root->_left;
}
else
{
Newnode* maxleft = root->_left;
while (maxleft->_left)
{
maxleft = maxleft->_right;
}
swap(root->_key, maxleft->_key);
return _EraseR(root->_left, key);
}
delete del;
return true;
}
}
//中序遍历
void _Inorder(Newnode* root)
{
if (root == nullptr) {
return;
}
_Inorder(root->_left);
cout << root->_key << " ";
_Inorder(root->_right);
}
private:
Newnode* _root = nullptr;
};
以上便是关于二叉搜索树的模拟实现。感谢大家的观看与支持!!!