二叉搜索树(BinarySearchTree)
所有左子树的值都小于根,所有右子树的值都大于根
用处:在内存中查找
最多查找高度次
如果能做到满二叉树或完全二叉树,在中国14亿人中找到心动的人只需要31次,10亿是30次(2的三十次方)
查找的话:需要后期的平衡二叉树,和AVL树
搜索二叉树中序遍历时一定程度上是有序的,所以又被叫做排序二叉树
比较数据的大小,我们在声明模板的时候一般申请成key - --class K
Insert操作
先序遍历可以排序+去重
查找Find也很简单
删除操作
#pragma once
#include<iostream>
#include<cstdio>
using namespace std;
//二叉树以后,模板参数用K(key)
template<class K>
struct BSTreeNode
{
BSTreeNode<K>* left;
BSTreeNode<K>* right;
K _val;
BSTreeNode(const K& val)
:left(nullptr)
,right(nullptr)
,_val(val)
{}
};
template<class K>
class BSTree
{
typedef BSTreeNode<K> Node;
public:
BSTree()
:_root(nullptr)
{}
bool Insert(const K& val)
{
if (_root == nullptr)
{
_root = new Node(val);
return true;
}
Node* parent = nullptr;
Node* cur = _root;
while (cur)
{
if (cur->_val < val)
{
parent = cur;
cur = cur->right;
}
else if (cur->_val > val)
{
parent = cur;
cur = cur->left;
}
else
{
return false;//树中不允许有相同的元素存在
}
}
//已经找到了位置,开始放结点
//想要链接的话,必须要通过parent
//单靠自己所在位置是链接不了的
cur = new Node(val);
if (parent->_val < val)
{
parent->right = cur;
}
else
{
parent->left = cur;
}
return true;
}
bool Find(const K& val)
{
Node* cur = _root;
while (cur)
{
if (cur->_val < val)
{
cur = cur->right;
}
else if (cur->_val > val)
{
cur = cur->left;
}
else
{
return true;
}
}
return false;
}
bool Erase(const K& val)
{
Node* parent = nullptr;
Node* cur = _root;
//开始找需要删除的元素
while (cur)
{
if (cur->_val < val)
{
parent = cur;
cur = cur->right;
}
else if (cur->_val > val)
{
parent = cur;
cur = cur->left;
}
else
{
//找到了以后分三种情况
//1 .该结点没有孩子 2 .该节点没有孩子 3.该节点有两个孩子
//前两种情况可以直接删除,最后一种情况可以用替换法删除
//将左子树的最右结点(也就是最大结点)或者右子树的最小节点(最左)交换删除
if (cur->left == nullptr)
{
//如果是根结点,特殊处理
if (parent == nullptr)
{
_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 (parent == nullptr)
{
_root = cur->left;
}
else
{
if (parent->left == cur)
{
parent->left = cur->left;
}
else
{
parent->right = cur->left;
}
}
delete cur;
}
else
{
//该结点既有左孩子又有右孩子,那么我们找左树的最大或者右树的最小
//在这里我们找右树的最小(也就是最左子树)
Node* minParent = cur;
Node* min = cur->right;
//找小
while (min->left)
{
minParent = min;
min = min->left;
}
cur->_val = min->_val;
if (minParent->left == min)
{
minParent->left = min->right;
}
else
{
minParent->right = cur->right;
}
delete min;
}
return true;
}
}
//没有找到
return false;
}
//递归写法写一个中序遍历
// 中序遍历就是排升序
//写一个_InOrder进行辅助递归
void InOrder()
{
_InOrder(_root);
}
void _InOrder(Node* root)
{
if (root == nullptr)
{
return;
}
_InOrder(root->left);
cout << root->_val << " ";
_InOrder(root->right);
}
bool InsertR(const K& key)
{
return _InsertR(_root, key);
}
Node* FindR(Node* root, const K& key)
{
return _FindR(root, key);
}
bool EraseR(Node* root, const K& key)
{
_EraseR(root, key);
}
private:
bool _EraseR(Node* root, const K& key)
{
if (root == nullptr)
{
return false;
}
if (root->_val < key)
{
return _EraseR(root->right, key);
}
else if (root->_val > key)
{
return _EraseR(root->left, key);
}
else
{
Node* del = root;
if (root->left == nullptr)
{
root = root->right;
}
else if (root->right == nullptr)
{
root = root->left;
}
else
{
Node* min = root->right;
while (min)
{
min = min->left;
}
swap(min->_val, del->_key);
_EraseR(root->right, key);
}
delete del;
}
}
Node* _FindR(Node* root, const K& key)
{
if (root == nullptr)
{
return root;
}
if (root->_val < key)
{
return _FindR(root->right, key);
}
else if (root->_val > key)
{
return _FindR(root->left, key);
}
else
{
return root;
}
}
bool _InsertR(Node*& root,const K& key)
{
if (root == nullptr)
{
root = new Node(key);
return true;
}
if (root->_val < key)
{
return _InsertR(root->right, key);
}
else if (root->_val > key)
{
return _InsertR(root->left, key);
}
else
{
return false;
}
}
Node* _root;
};
void TestBSTree()
{
BSTree<int> t;
int a[] = { 5, 3, 4, 1, 7, 8, 2, 6, 0, 9,5,5 };
for (auto e : a)
{
t.Insert(e);
}
t.InOrder();
printf("\n");
t.Erase(5);
t.InOrder();
}