目录
- 1.什么是二叉搜索树
- 2.构建二叉搜索树
- 2.1首先搭建树的框架
- 2.2搭建搜索树的框架
- 3.二叉搜索树的插入
- 3.1非递归式插入
- 3.2递归式插入
- 4.二叉搜索树的查找
- 4.1非递归查找
- 4.2递归查找
- 5.二叉搜索树的删除
- 5.1非递归删除
- 5.2递归删除
- 6.整个代码实现
1.什么是二叉搜索树
简单来讲就是一个树的左子树的值都小于根,右子树的值都大于根。如:
这个树的特点是走一趟中序就完成了对一组树的排序。查找一个树也特别的方便,最多只需要走树的高度次。所以当这个树比较饱满时搜索的效率很高,所以被称为二叉搜索树。
2.构建二叉搜索树
2.1首先搭建树的框架
struct TreeNode
{
TreeNode<V>* _left;
TreeNode<V>* _right;
V _val;
//构造函数
TreeNode(V val)
{
_left = nullptr;
_right = nullptr;
_val = val;
}
};
2.2搭建搜索树的框架
template<class V>
class BSTree
{
typedef TreeNode<V> Node;
public:
BSTree()
{
_head = nullptr;
}
private:
Node* _head;
};
3.二叉搜索树的插入
3.1非递归式插入
1.思路
2.代码
//插入(非递归)
bool insert(V val)
{
if (_head == nullptr)
{
_head = new Node(val);
return true;
}
//找到要插入结点的位置
Node* parent = _head;
Node* cur = _head;
while (cur)
{
if (cur->_val < val)
{
parent = cur;
cur = cur->_right;
}
else if (cur->_val > val)
{
parent = cur;
cur = cur->_left;
}
else
{
//相等 返回false
return false;
}
}
//判断val插在parent的左还是右
if (parent->_val >val)
{
parent->_left = new Node(val);
return true;
}
else
{
parent->_right = new Node(val);
return true;
}
3.2递归式插入
bool insertR(V val)
{
return _insertR(_head, val);
}
bool _insertR(Node*& head, V val)
{
if (head == nullptr)
{
head = new Node(val);
return true;
}
if (head->_val > val)
{
_insertR(head->_left,val);
}
else if (head->_val < val)
{
_insertR(head->_right, val);
}
else
{
return false;
}
return false;
}
注意点:这个递归式插入其实也没什么难的,就是有个注意点是要引用传参。如果不是引用传参是不会修改-head的。
4.二叉搜索树的查找
4.1非递归查找
//非递归查找
bool find(V val)
{
if (_head == nullptr)
{
return false;
}
Node* cur = _head;
while (cur)
{
if (cur->_val < val)
{
cur = cur->_right;
}
else if (cur->_val > val)
{
cur = cur->_left;
}
else
{
return true;
}
}
}
4.2递归查找
bool findR(const V& val)
{
return _findR(_head, val);
}
bool _findR(Node* head, const V& val)
{
if (head == nullptr)
{
return false;
}
if (head->_val == val)
{
return true;
}
return _findR(head->_left, val) || _findR(head->_right, val);
}
比较常规,没什么要解释的。
5.二叉搜索树的删除
5.1非递归删除
算法思路:
代码实现:
//非递归式删除
bool erase(const V& val)
{
//第一步找到要删除的结点
Node* parent = _head;
Node* cur = _head;
while (cur)
{
if (cur->_val > val)
{
parent = cur;
cur = cur->_left;
}
else if (cur->_val < val)
{
parent = cur;
cur = cur->_right;
}
else
{
//找到了
//分情况讨论
if (cur->_left == nullptr)
{
//特殊情况
if (cur == _head)
{
_head = _head->_right;
return true;
}
if (parent->_left == cur)
{
parent->_left = cur->_right;
}
else
{
parent->_right = cur->_right;
}
delete cur;
return true;
}
else if (cur->_right == nullptr)
{
//特殊情况
if (cur == _head)
{
_head = _head->_left;
return true;
}
if (parent->_left == cur)
{
parent->_left = cur->_left;
}
else
{
parent->_right = cur->_left;
}
delete cur;
return true;
}
else
{
//找LeftMax
Node* parent = cur;
Node* LeftMax = cur->_left;
while (LeftMax->_right)
{
parent = LeftMax;
LeftMax = LeftMax->_right;
}
//交换cur与LeftMax的val
swap(cur->_val, LeftMax->_val);
if (parent->_left == LeftMax)
{
parent->_left = LeftMax->_right;
}
else
{
parent->_right = LeftMax->_right;
}
delete LeftMax;
return true;
}
}
}
return false;
}
注:这个非递归主要就是要完全考虑到删除结点会出现的可能,代码实现不复杂,但是很难一起写对,写错了调试也好很久(本人亲身经历调试了一个下午)。
5.2递归删除
算法思路:
代码实现:
bool _eraseR(Node*& head, const V& val)
{
if (head == nullptr)
{
return false;
}
else if (head->_val > val)
{
_eraseR(head->_left, val);
}
else if (head->_val < val)
{
_eraseR(head->_right, val);
}
else
{
//递归找到了
Node* del = head;
//三种情况
//1.左子树为空
if (head->_left == nullptr)
{
head = head->_right;
}
//2.右子树为空
else if(head->_right == nullptr)
{
head = head->_left;
}
//3.左右子树都不为空
else
{
//找LeftMax
Node* LeftMax = head->_left;
while (LeftMax->_right)
{
LeftMax = LeftMax->_right;
}
//交换
swap(head->_val, LeftMax->_val);
//递归删除
return _eraseR(head->_left, val);
}
delete del;
return true;
}
}
6.整个代码实现
#pragma once
template<class V>
struct TreeNode
{
TreeNode<V>* _left;
TreeNode<V>* _right;
V _val;
//构造函数
TreeNode(V val)
{
_left = nullptr;
_right = nullptr;
_val = val;
}
};
template<class V>
class BSTree
{
typedef TreeNode<V> Node;
public:
BSTree()
{
_head = nullptr;
}
//深拷贝
BSTree(BSTree<V>& bs)
{
_head = CopyTree(bs._head);
}
//赋值
BSTree<V>& operator=(BSTree<V> bs)
{
swap(_head, bs._head);
return *this;
}
//插入(非递归)
bool insert(V val)
{
if (_head == nullptr)
{
_head = new Node(val);
return true;
}
//找到要插入结点的位置
Node* parent = _head;
Node* cur = _head;
while (cur)
{
if (cur->_val < val)
{
parent = cur;
cur = cur->_right;
}
else if (cur->_val > val)
{
parent = cur;
cur = cur->_left;
}
else
{
//相等 返回false
return false;
}
}
//判断val插在parent的左还是右
if (parent->_val >val)
{
parent->_left = new Node(val);
return true;
}
else
{
parent->_right = new Node(val);
return true;
}
}
bool insertR(V val)
{
return _insertR(_head, val);
}
//非递归查找
bool find(V val)
{
if (_head == nullptr)
{
return false;
}
Node* cur = _head;
while (cur)
{
if (cur->_val < val)
{
cur = cur->_right;
}
else if (cur->_val > val)
{
cur = cur->_left;
}
else
{
return true;
}
}
}
bool findR(const V& val)
{
return _findR(_head, val);
}
~BSTree()
{
destory(_head);
}
void inorder()
{
_inorder(_head);
cout << endl;
}
//非递归式删除
bool erase(const V& val)
{
//第一步找到要删除的结点
Node* parent = _head;
Node* cur = _head;
while (cur)
{
if (cur->_val > val)
{
parent = cur;
cur = cur->_left;
}
else if (cur->_val < val)
{
parent = cur;
cur = cur->_right;
}
else
{
//找到了
//分情况讨论
if (cur->_left == nullptr)
{
//特殊情况
if (cur == _head)
{
_head = _head->_right;
return true;
}
if (parent->_left == cur)
{
parent->_left = cur->_right;
}
else
{
parent->_right = cur->_right;
}
delete cur;
return true;
}
else if (cur->_right == nullptr)
{
//特殊情况
if (cur == _head)
{
_head = _head->_left;
return true;
}
if (parent->_left == cur)
{
parent->_left = cur->_left;
}
else
{
parent->_right = cur->_left;
}
delete cur;
return true;
}
else
{
//找LeftMax
Node* parent = cur;
Node* LeftMax = cur->_left;
while (LeftMax->_right)
{
parent = LeftMax;
LeftMax = LeftMax->_right;
}
//交换cur与LeftMax的val
swap(cur->_val, LeftMax->_val);
if (parent->_left == LeftMax)
{
parent->_left = LeftMax->_right;
}
else
{
parent->_right = LeftMax->_right;
}
delete LeftMax;
return true;
}
}
}
return false;
}
bool eraseR(const V& val)
{
return _eraseR(_head, val);
}
private:
Node* _head;
void destory(Node*& head)
{
if (head == nullptr)
{
return;
}
destory(head->_left);
destory(head->_right);
delete head;
head = nullptr;
}
bool _insertR(Node*& head, V val)
{
if (head == nullptr)
{
head = new Node(val);
return true;
}
if (head->_val > val)
{
_insertR(head->_left,val);
}
else if (head->_val < val)
{
_insertR(head->_right, val);
}
else
{
return false;
}
return false;
}
void _inorder(Node* head)
{
if (head == nullptr)
{
return;
}
_inorder(head->_left);
cout << head->_val << " ";
_inorder(head->_right);
}
bool _findR(Node* head, const V& val)
{
if (head == nullptr)
{
return false;
}
if (head->_val == val)
{
return true;
}
return _findR(head->_left, val) || _findR(head->_right, val);
}
bool _eraseR(Node*& head, const V& val)
{
if (head == nullptr)
{
return false;
}
else if (head->_val > val)
{
_eraseR(head->_left, val);
}
else if (head->_val < val)
{
_eraseR(head->_right, val);
}
else
{
//递归找到了
Node* del = head;
//三种情况
//1.左子树为空
if (head->_left == nullptr)
{
head = head->_right;
}
//2.右子树为空
else if(head->_right == nullptr)
{
head = head->_left;
}
//3.左右子树都不为空
else
{
//找LeftMax
Node* LeftMax = head->_left;
while (LeftMax->_right)
{
LeftMax = LeftMax->_right;
}
//交换
swap(head->_val, LeftMax->_val);
//递归删除
return _eraseR(head->_left, val);
}
delete del;
return true;
}
}
Node* CopyTree(Node* head)
{
if (head == nullptr)
{
return nullptr;
}
Node* newhead = new Node(head->_val);
newhead->_left = CopyTree(head->_left);
newhead->_right = CopyTree(head->_right);
return newhead;
}
};