二叉搜索树
文章目录
1、概述
二叉搜索树(BST)是二叉树的一种特殊形式。
二叉搜索树具有以下性质:每个节点中的值必须大于(或等于)其左侧子树中的任何值,且小于(或等于)其右侧子树中的任何值。
本节将更详细地介绍二叉搜索树的定义,并提供一些与二叉搜索树相关的习题。
完成后,你将:
- 理解二叉搜索树的特性
- 熟悉二叉搜索树中的基本操作,及其相关算法思想
- 尝试用C++实现二叉搜索树
- 完成leetcode BST 入门习题
- 理解高度平衡二叉树的概念
2、二叉搜索树的定义
二叉搜索树(BST)
是二叉树的一种特殊表现形式,它满足一下特性:
- 每个节点中的值必须
大于
(或等于)存储在其左侧子树中的任何值。 - 每个节点中的值必须
小于
(或等于)存储在其右子树中的任何值。
下面是一个二叉搜索树的🌰:
3、相关入门习题
【1】验证二叉搜索树
1)解法一:递归
bool helper(TreeNode* root,long long lower,long long upper){
if(!root)return true;
if(root -> val <= lower || root -> val >= upper)return false;
return helper(root->left,lower,root->val)&&helper(root->right,root->val,upper);
}
bool isValidBST(TreeNode* root) {
return helper(root,LONG_MIN,LONG_MAX);
}
2) 解法二:中序遍历
对二叉搜索树进行中序遍历将得到递增序列
long long pre=LONG_MIN;
bool isValidBST(TreeNode* root) {
if (!root)
return true;
// 访问左子树
if (!isValidBST(root->left)) return false;
// 访问当前节点:如果当前节点小于等于中序遍历的前一个节点,说明不满足BST,返回 false;否则继续遍历。
if (root->val <= pre) return false;
pre = root->val;
// 访问右子树
return isValidBST(root->right);
}
【2】二叉搜索树迭代器
class BSTIterator {
//设计题
public:
queue<TreeNode*>q;
BSTIterator(TreeNode* root) {
midorder(root);
}
void midorder(TreeNode* root){
if(!root)return;
midorder(root->left); //中序遍历直接走
q.push(root);
midorder(root->right);
}
int next() {
int k=q.front()->val;//以队列头部作为迭代器的位置
q.pop();
return k;
}
bool hasNext() {
return !q.empty();
}
};
4、二叉搜索树的基本操作
1-搜索操作
根据BST的特性,对于每个节点:
- 如果目标值等于节点的值,则返回节点;
- 如果目标值小于节点的值,则继续在左子树中搜索;
- 如果目标值大于节点的值,则继续在右子树中搜索。
我们一起来看一个例子:我们在上面的二叉搜索树中搜索目标值为 4 的节点。
代码示例
TreeNode* searchBST(TreeNode* root, int val) {
if(!root)return nullptr;
if(val<root->val)return searchBST(root->left,val);
else if(val>root->val)return searchBST(root->right,val);
else return root;
}
2-插入操作
二叉搜索树中的另一个常见操作是插入一个新节点。有许多不同的方法去插入新节点,这篇文章中,我们只讨论一种使整体操作变化最小的经典方法。 它的主要思想是为目标节点找出合适的叶节点位置,然后将该节点作为叶节点插入。 因此,搜索将成为插入的起始。
与搜索操作类似,对于每个节点,我们将:
- 根据节点值与目标节点值的关系,搜索左子树或右子树;
- 重复步骤 1 直到到达外部节点;
- 根据节点的值与目标节点的值的关系,将新节点添加为其左侧或右侧的子节点。
与搜索操作相同,我们可以递归或迭代地进行插入。 它的解决方案也与搜索非常相似,你应该可以自己实现,并以相同的方式分析算法的时间复杂度和空间复杂度。
代码示例:
TreeNode* insertIntoBST(TreeNode* root, int val) {
if (root==nullptr) {
return new TreeNode(val);
}
if (val < root->val) {
root->left = insertIntoBST(root->left, val);
} else {
root->right = insertIntoBST(root->rig