数据结构---【二叉搜索树】

必须满足的条件:左子树中所有节点的值< 根节点的值 < 右子树中所有节点的值

任意节点的左右子树也是搜索二叉树,也要满足上面的条件

二叉搜索树与堆不同,不一定是完全二叉树,采用链式结构

搜索二叉树的中序遍历是升序

1、查找

数据大于根 往右走 小于根往左走

cpp 复制代码
TreeNode* search(BinarySearchTree* bst,int num)
{
    TreeNode* cur = bst->root;
    while(cur != NULL)
    {
        if(cur->data < num)
        {    cur = cur -> right; }
        else{ cur= cur -> left;}
        else  break; 
    }
    return cur;
}

2、插入节点

//1、判断树是否为空 为空创建节点 把数据放入
//2、树不为空 首先判断 这个要插入的数据是否重复 重复直接返回,cur指向要插入数据的位置 perv指向要插入数据的父亲节点
//3、找到位置
//4、将父亲的左/右指向插入的数据节点(看num的值大于prev->data还是小于,大于就是right指向node,小于就是left

cpp 复制代码
void insert(BinarySearchTree* bst, int num)
{
    //1、判断树是否为空 为空创建节点 把数据放入
    //2、树不为空 首先判断 这个要插入的数据是否重复 cur指向要插入数据的位置 perv指向要插入数据的父亲节点
    //3、找到位置
    //4、将父亲的左/右指向插入的数据节点
    if(bst -> root = NULL)
    {
        bst->root = newTreeNode(num);//创建新节点 把数据放进去
        return;
    }
    TreeNode* cur = bst->root, *prev = NULL;
    while(cur != NULL) //等于NULL不能再进入循环
    {
        if(cur->data = num)
        { return; }
        prev = cur;
        if(cur -> data < num)
        { cur = cur -> right; }
        else { cur = cur ->left;}
    }
    TreeNode* node = newTreeNode(num);
    if(prev -> data < num)
    { prev ->right = node;}
    else { prev -> left = node;}
}

3、删除节点

1、找到要删除的节点

2、看节点的度

节点度为0/1:让要被删除的节点的父亲节点指向要被删除的节点的孩子

节点度为2:找替换节点;找左子树中的最大的或者右子树中的最小的。

查找cur在中序遍历中的下一个节点(即右子树的最小值);将找到的这个节点删除;将删除节点的值赋值给cur的值。

cpp 复制代码
void removeItem(BinarySearchTree* bst, int num)
{
    if(bst -> root == NULL)
    { return;}
    TreeNode* cur = bst->root, *prev = NULL;
    while(cur != NULL) //cur可以指向空,只是指向空之后就不能再进入循环了
    {
        if(cur->data = num)  break;
        prev = cur;
        if(cur -> data < num)
        { cur = cur -> right;}
        else { cur = cur -> left;}
    }
    if(cur == NULL) return; //没有找到要删除的值 直接退出
    if(cur->left == NULL || cur->right == NULL)
    {    TreeNode* child = cur ->left != NULL ? cur->left : cur->right;
         if(pre->right == cur){pre ->right = child;}
         else{ pre->left =child;}
         free(cur);
    }
    else{   
            TreeNode* tmp = cur->right;
            while(tmp->left !=NULL)
            {tmp = tmp -> left;}
            int tmpval = tmp->data;
            removeItem(bst,tmp->val);//删除找到的右子树的最小值
            cur -> data = tmpval;
        }
}   
cpp 复制代码
class Solution {
public:
    bool isValidBSTHelp(struct TreeNode* root,long min_val, long max_val)
    {
        if(root == NULL)  return true;//空树也是BST
        if(root->val <= min_val || root->val >= max_val) 
        return false; //树根的值必须在这个范围内
        //根的值是左子树的上界 是右子树的下界 两个同时满足才可返回true
        return isValidBSTHelp(root->left,min_val,root->val)&&
            isValidBSTHelp(root->right,root->val,max_val);
    }
    bool isValidBST(TreeNode* root)
    {
        return isValidBSTHelp(root,LONG_MIN,LONG_MAX);//两个宏值
    }
};
cpp 复制代码
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

 //从根节点开始遍历
 //如果插入的值大于根往右走,判断根的右是不是为空
 //为空直接建节点就让pos->right = val
 //走一步判断右(pos->right)是否为空,为空就pos->right = val
 //左边也是同理

struct TreeNode* creatTreeNode(int val) {
    struct TreeNode* ret = malloc(sizeof(struct TreeNode));
    ret->val = val;
    ret->left = ret->right = NULL;
    return ret;
}
struct TreeNode* insertIntoBST(struct TreeNode* root, int val) {
    if (root == NULL) {
        root = creatTreeNode(val);
        return root;
    }
    struct TreeNode* pos = root;//指向根
    while (pos != NULL) {
        if (val < pos->val) { //往左走
            if (pos->left == NULL) { //看左边是不是为空
                pos->left = creatTreeNode(val); //为空直接链入左子树
                break;
            } else {
                pos = pos->left; //左不为空继续往左走
            }
        } else {
            if (pos->right == NULL) {
                pos->right = creatTreeNode(val);
                break;
            } else {
                pos = pos->right;
            }
        }
    }
    return root;
}
cpp 复制代码
class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        TreeNode *cur = root, *curParent = nullptr;
        while (cur && cur->val != key) {
            curParent = cur;
            if (cur->val > key) {
                cur = cur->left;
            } else {
                cur = cur->right;
            }
        }
        if (!cur) {
            return root;
        }
        if (!cur->left && !cur->right) {
            cur = nullptr;
        } else if (!cur->right) {
            cur = cur->left;
        } else if (!cur->left) {
            cur = cur->right;
        } else {
            TreeNode *successor = cur->right, *successorParent = cur;
            while (successor->left) {
                successorParent = successor;
                successor = successor->left;
            }
            if (successorParent->val == cur->val) {
                successorParent->right = successor->right;
            } else {
                successorParent->left = successor->right;
            }
            successor->right = cur->right;
            successor->left = cur->left;
            cur = successor;
        }
        if (!curParent) {
            return cur;
        } else {
            if (curParent->left && curParent->left->val == key) {
                curParent->left = cur;
            } else {
                curParent->right = cur;
            }
            return root;
        }
    }
};
相关推荐
嵌入式@秋刀鱼4 小时前
《第四章-筋骨淬炼》 C++修炼生涯笔记(基础篇)数组与函数
开发语言·数据结构·c++·笔记·算法·链表·visual studio code
嵌入式@秋刀鱼4 小时前
《第五章-心法进阶》 C++修炼生涯笔记(基础篇)指针与结构体⭐⭐⭐⭐⭐
c语言·开发语言·数据结构·c++·笔记·算法·visual studio code
泽02024 小时前
C++之list的自我实现
开发语言·数据结构·c++·算法·list
物联网嵌入式小冉学长7 小时前
2.线性表的链式存储-链表
数据结构·链表
顾小玙7 小时前
前缀和:leetcode974--和可被K整除的子数组
数据结构·算法
W说编程8 小时前
算法导论第三章:数据结构艺术与高效实现
c语言·数据结构·算法
hn小菜鸡8 小时前
LeetCode 2917.找出数组中的K-or值
数据结构·算法·leetcode
yield-bytes9 小时前
Java并发进阶系列:深度讨论高并发跳表数据结构ConcurrentSkipListMap的源代码实现(上)
数据结构
好易学·数据结构10 小时前
可视化图解算法51:寻找第K大(数组中的第K个最大的元素)
数据结构·python·算法·leetcode·力扣·牛客网·堆栈
NULL指向我11 小时前
C语言数据结构笔记5:Keil 编译器优化行为_malloc指针内存分配问题
c语言·数据结构·笔记