目录
一、二叉搜索树
⭐1.1 二叉搜索树的概念
⭐1.2 二叉搜索树具有的性质:
⭐ 二、二叉搜索树的相关操作
⭐2.1二叉搜索树的节点的类型
⭐2.2二叉搜索树的查找(非递归)
⭐ 2.3二叉搜索树的查找(递归)
⭐2.4二叉搜索树的插入(非递归)
⭐2.5二叉搜索树的插入(递归)
⭐2.6二叉搜索树的删除(非递归)
⭐2.7二叉搜索树的删除(递归)
⭐2.8二叉搜索树的遍历
⭐2.9二叉树的拷贝构造及构造,赋值重载
⭐三、二叉搜索树的全部代码
二叉搜索树又称二叉排序树,是一种特殊有序的二叉树。
①二叉搜索树的查找
②二叉搜索树的插入
③二叉搜索树的删除
template //类模板
struct BSTNode
{
BSTNode* left;
BSTNode* right;
K _key;
BSTNode(K key)
:left(nullptr)
, right(nullptr)
, _key(key)
{}
};
从根开始查找,如果要查找的值比根节点大就往右子树走,如果比根节点小就往左子树走,依次循环,直到找到或走到空,则结束。找到则返回true,找不到返回false。
bool find(const K& key)
{
BSTNode* cur = _root;
while (cur)
{
if (cur->_key == key)
return true;
else if (cur->_key < key)
cur = cur->right;
else
cur = cur->left;
}
return false;
}
思路和非递归是一样的,如果查找的节点为空表示该树中没有该节点,返回false,如果找到了就返回true
bool _findR(BSTNode* root, const K& key)
{
if (!root)return false;
if (root->_key == key)
return true;
else if (root->_key > key)
return _findR(root->left, key);//往左子树走
else
return _findR(root->right, key);//往右子树走
}
判断树是否为空,如果树为空的话,那么直接新增一个节点,并把该节点的地址赋给_root指针(指向根节点的指针)。如果树不为空,那么就按照二叉搜索树的查找方法,找到插入的位置,然后将新节点插入。注意:如果相等那么将返回false,不能插入
bool insert(const K& key)
{
if (_root == nullptr)
{
_root= new BSTNode(key);
return true;
}
BSTNode* cur = _root, *parent=nullptr;
while (cur)
{
if (_root->_key < key)
{
parent = cur;
cur = cur->right;
}
else if (_root->_key > key)
{
parent = cur;
cur = cur->left;
}
else
return false;
}
BSTNode* newnode = new BSTNode(key);
if (parent->_key < key)
{ //插入的节点大于该插入位置的父节点,往右边插入
parent->right = newnode;
}
else
{ //插入的节点小于该插入位置的父节点,往左边插入
parent->left = newnode;
}
return true;
}
这里传的是引用,形参的改变可以影响实参,所以直接给root赋值了
bool _InsertR(BSTNode*& root, const K& key)
{ //如果根节点为空,直接把值赋给root
if (!root)
BSTNode* root = new BSTNode(key);
if (root->_key > key)
{
return _InsertR(root->left, key);
}
else if (root->_key < key)
{
return _InsertR(root->right, key);
}
else
return false;
}
首先查找元素是否在二叉搜索树中,如果不存在,则返回, 否则要删除的结点可能分下面四种情
况:
看起来有待删除节点有4种情况,实际情况1可以与情况2或者3合并起来,因此真正的删除过程
如下:
bool Erase(const K& key)
{
BSTNode* cur = _root, * parent =nullptr;
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)
{
_root = _root->right;
}
else if (parent->left == cur)
{
parent->left = cur->right;
}
else
{
parent->right = cur->right;
}
delete cur;
}
//没有右孩子节点
else if (cur->right == nullptr)
{
if (parent == nullptr)
{
_root = _root->right;
}
else if (parent->left == cur)
{
parent->left = cur->left;
}
else
{
parent->right = cur->left;
}
delete cur;
}
//左右孩子都有的节点
else
{
BSTNode*minparent = cur;
BSTNode* minright = cur->right;
while (minright->left)
{
minparent = minright;
minright = minright->left;
}
swap(minright->_key, cur->_key);
if (minparent->left = minright)
{
minparent->left = minright->right;
}
else
{
minparent->right = minright->right;
}
delete minright;
}
}
return true;
}
return false;
}
bool _EraseR(BSTNode*& root, const K& key)//传引用
{
if (!root)return false;
if (root->_key == key)
{
BSTNode* del = root;
// 删除
if (root->left == nullptr)
{
root = root->right;
}
else if (root->right == nullptr)
{
root = root->left;
}
else
{
BSTNode* minRight = root->right;
while (minRight->left)
{
minRight = minRight->left;
}
swap(root->_key, minRight->_key);
//交换完以后继续递归删除
return _EraseR(root->right, key);
}
delete del;
return true;
}
else if (root->_key > key)
return _EraseR(root->left, key);
else
return _EraseR(root->right, key);
}
当创建好二叉搜索树后,我们需要知道自己的相关操作对不对,所以需要遍历二叉搜索树来验证,
那什么遍历方式好呢?这里选的是中序遍历,因为二叉搜索树左边都是小于根节点的,右边都是大于根节点的,所以使用中序遍历可以得到一个呈升序的序列
void _Inorder(BSTNode* root)
{
if (!root)return;
_Inorder(root->left);
cout << root->_key << ' ';
_Inorder(root->right);
}
//C++11支持的编译器强制生成默认构造函数
//BST() = default;
BST()//构造
{}
BSTNode* CopyTree( BSTNode* root)
{
if (root == nullptr)
return nullptr;
BSTNode* copyNode = new BSTNode(root->_key);
copyNode->_left = CopyTree(root->_left);
copyNode->_right = CopyTree(root->_right);
return copyNode;
}
BST(const BST& bst)//拷贝构造
{
_root = CopyTree(bst);
}
BST& operator=(const BST bst)//赋值重载
{
swap(_root, bst._root);
return *this;
}
#pragma once
#include
using namespace std;
template
struct BSTNode
{
BSTNode* left;
BSTNode* right;
K _key;
BSTNode(K key)
:left(nullptr)
, right(nullptr)
, _key(key)
{}
};
template
class BST
{
public:
//C++11支持的编译器强制生成默认构造函数
//BST() = default;
BST()
{}
BSTNode* CopyTree( BSTNode* root)
{
if (root == nullptr)
return nullptr;
BSTNode* copyNode = new BSTNode(root->_key);
copyNode->_left = CopyTree(root->_left);
copyNode->_right = CopyTree(root->_right);
return copyNode;
}
BST(const BST& bst)
{
_root = CopyTree(bst);
}
BST& operator=(const BST bst)
{
swap(_root, bst._root);
return *this;
}
bool find(const K& key)
{
BSTNode* cur = _root;
while (cur)
{
if (cur->_key == key)
return true;
else if (cur->_key < key)
cur = cur->right;
else
cur = cur->left;
}
return false;
}
bool insert(const K& key)
{
if (_root == nullptr)
{
_root= new BSTNode(key);
return true;
}
BSTNode* cur = _root, *parent=nullptr;
while (cur)
{
if (_root->_key < key)
{
parent = cur;
cur = cur->right;
}
else if (_root->_key > key)
{
parent = cur;
cur = cur->left;
}
else
return false;
}
BSTNode* newnode = new BSTNode(key);
if (parent->_key < key)
{
parent->right = newnode;
}
else
parent->left = newnode;
return true;
}
bool Erase(const K& key)
{
BSTNode* cur = _root, * parent =nullptr;
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)
{
_root = _root->right;
}
else if (parent->left == cur)
{
parent->left = cur->right;
}
else
{
parent->right = cur->right;
}
delete cur;
}
else if (cur->right == nullptr)
{
if (parent == nullptr)
{
_root = _root->right;
}
else if (parent->left == cur)
{
parent->left = cur->left;
}
else
{
parent->right = cur->left;
}
delete cur;
}
else
{
BSTNode*minparent = cur;
BSTNode* minright = cur->right;
while (minright->left)
{
minparent = minright;
minright = minright->left;
}
swap(minright->_key, cur->_key);
if (minparent->left = minright)
{
minparent->left = minright->right;
}
else
{
minparent->right = minright->right;
}
delete minright;
}
}
return true;
}
return false;
}
void Inorder()
{
_Inorder(_root);
cout << endl;
}
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);
}
private:
void _Inorder(BSTNode* root)
{
if (!root)return;
_Inorder(root->left);
cout << root->_key << ' ';
_Inorder(root->right);
}
bool _findR(BSTNode* root, const K& key)
{
if (!root)return false;
if (root->_key == key)
return true;
else if (root->_key > key)
return _findR(root->left, key);
else
return _findR(root->right, key);
}
bool _InsertR(BSTNode*& root, const K& key)
{
if (!root)
BSTNode* root = new BSTNode(key);
if (root->_key > key)
{
return _InsertR(root->left, key);
}
else if (root->_key < key)
{
return _InsertR(root->right, key);
}
else
return false;
}
bool _EraseR(BSTNode*& root, const K& key)
{
if (!root)return false;
if (root->_key == key)
{
BSTNode* del = root;
// 删除
if (root->left == nullptr)
{
root = root->right;
}
else if (root->right == nullptr)
{
root = root->left;
}
else
{
BSTNode* minRight = root->right;
while (minRight->left)
{
minRight = minRight->left;
}
swap(root->_key, minRight->_key);
return _EraseR(root->right, key);
}
delete del;
return true;
}
else if (root->_key > key)
return _EraseR(root->left, key);
else
return _EraseR(root->right, key);
}
BSTNode* _root = nullptr;
};
二叉搜索树的知识就分享到这里了,有什么错误还望指出。