1.什么是二叉搜索树
二叉搜索树就是又来搜索的一棵树,将数据存入这棵树中,以左子树比根节点小,右子树比根节点大的方式存入,它可以一较快的方式查找,删除,插入数据,不能被修该,时间复杂度为·O(h),h为这棵树的高度。
2.二叉搜索树的实现
二叉树的实现有两类,分为递归和非递归实现,具体看代码。
二叉树的查找:
从根开始比较,查找,比根大则往右边走查找,比根小则往左边走查找。最多查找高度次,走到到空,还没找到,这个值不存在。
二叉树的插入:
树为空,则直接新增节点,赋值给root指针,树不空,按二叉搜索树性质查找插入位置,插入新节点。
二叉树的删除:
首先查找元素是否在二叉搜索树中,如果不存在,则返回, 否则要删除的结点可能分下面四种情况:
- 要删除的结点无孩子结点
- 要删除的结点只有左孩子结点
- 要删除的结点只有右孩子结点
- 要删除的结点有左、右孩子结点
看起来有待删除节点有4中情况,实际情况1可以与情况2或者3合并起来,因此真正的删除过程
如下:
- 删除该结点且使被删除节点的双亲结点指向被删除节点的左孩子结点--直接删除。
- 删除该结点且使被删除节点的双亲结点指向被删除结点的右孩子结点--直接删除。
- 在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除节点中,再来处理该结点的删除问题--替换法删除.
#pragma once
#include <iostream>
using namespace std;
template<class k>
//定义BSTreeNode
struct BSTreeNode
{
BSTreeNode<k>* left;
BSTreeNode<k>* right;
k key;
BSTreeNode()
:left(nullptr),right(nullptr),key(0)
{}
};
//Tree
template<class T>
class BSTree
{
typedef BSTreeNode<T>* _Node;
public:
BSTree() = default;//C++用法,强制生成默认构造函数
//赋值重载
BSTreeNode<T>& operator=(BSTreeNode<T> t)
{
std::swap(root, t);
return *this;
}
析构函数
~BSTree()
{
~destory(root);
}
private:
//拷贝复制
_Node Copy(_Node root)
{
if (root == nullptr)
{
return nullptr;
}
_Node copyRoot = new BSTreeNode<T>(root->key);
copyRoot->left = _Copy(root->left);
copyRoot->right = _Copy(root->right);
return copyRoot;
}
//插入递归
bool insertR(_Node root, const T& key)
{
if (root == nullptr)
{
root = new BSTreeNode<T>(key);
return true;
}
if (root->key > key)
{
insertR(root->left, key);
}
else if (root->key < key)
{
insertR(root->right, key);
}
else
{
return false;
}
}
//查找递归
_Node findR(_Node root, const T& key)
{
if (root == nullptr)
{
return nullptr;
}
if (root->key > key)
{
findR(root->left, key);
}
else if (root->key < key)
{
findR(root->right, key);
}
else
{
return root;
}
}
//删除递归
bool eraseR(_Node root,const T& key)
{
if (root == nullptr)
return false;
if (root->key > key)
{
eraseR(root->left, key);
}
else if (root->key < key)
{
eraseR(root->right, key);
}
else
{
if (root->left == nullptr)
{
root = root->right;
delete[] root;
}
else if (root->right == nullptr)
{
root = root->left;
delete[] root;
}
else
{
_Node cur = root;
_Node minNode = root->right;
while (minNode->left)
{
minNode = minNode->left;
}
swap(root->key, minNode->key);
bool eraseR(root->right,key);
delete[] root;
}
return true;
}
}
//插入非递归
bool insert(_Node root,const T& key)
{
//判空
if (root == nullptr)
{
root = new BSTreeNode<T>(key);
return true;
}
//非空
_Node partant = nullptr;//父节点
_Node cur = root;//子节点
while (cur)
{
//判断
if (cur->key > key)
{
partant = cur;
cur = cur->left;
}
else if (cur->key < key)
{
partant = cur;
cur = cur->right;
}
else
{
return false;
}
}
//开辟空间
cur = new BSTreeNode<T>(key);
//比较
if (partant->key > key)
{
partant->left = cur;
}
else
{
partant->right = cur;
}
return true;
}
//查找迭代
_Node find(_Node root,const T& key)
{
if (root == nullptr)
{
return nullptr;
}
else
{
_Node cur = root;
while (cur)
{
//判断
if (cur->key > key)
{
cur = cur->left;
}
else if (cur->key < key)
{
cur = cur->right;
}
else
{
return cur;
}
}
return nullptr;
}
}
//删除迭代
bool erase(_Node root,const T& key)
{
if (root == nullptr)
return false;
_Node cur = root;
_Node parent = nullptr;
while (cur)
{
//判断
if (cur->key > key)
{
parent = cur;
cur = cur->left;
}
else if (cur->key < key)
{
parent = cur;
cur = cur->right;
}
else
{
//左为空
if (cur->left == nullptr)
{
if (cur == root)
{
root = cur->right;
}
else
{
if (cur == parent->left)
{
parent->left = cur->right;
}
else
{
parent->right = cur->right;
}
}
delete cur;
cur = nullptr;
}
//右为空
else if (cur->right == nullptr)
{
if (root == cur)
{
root = cur->left;
}
else
{
if (cur == parent->left)
{
parent->left = cur->left;
}
else
{
parent->right = cur->left;
}
}
delete cur;
cur = nullptr;
}
else
{
// 找到右子树最小节点进行替换
_Node minParent = cur;
_Node min = cur->right;
while (min->left)
{
minParent = min;
min = min->left;
}
//交换
swap(cur->key, min->key);
if (minParent->left == min)
minParent->left = min->right;
else
minParent->right = min->right;
delete min;
}
}
return true;
}
}
//中序遍历
void InOrder(_Node root)
{
if (root == nullptr)
return;
InOrder(root->left);
cout << root->key << endl;
InOrder(root->right);
}
//销毁
void _Destory(_Node& root)
{
if (root == nullptr)
{
return;
}
_Destory(root->left);
_Destory(root->right);
delete root;
root = nullptr;
}
private:
_Node root = nullptr;
};