IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【Java---数据结构】二叉搜索树 -> 正文阅读

[数据结构与算法]【Java---数据结构】二叉搜索树

目录

一、认识二叉搜索树

二、实现二叉搜索树

🍓查找

🍓插入

🍓删除

四、性能分析


一、认识二叉搜索树

🍎二叉搜索树是一种特殊的二叉树,二叉搜索树又称二叉排序树。

🍎空树也是二叉搜索树。

?二叉搜索树的特点:

  • 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
  • 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
  • 它的左右子树也分别为二叉搜索树
  • 二叉搜索树中的结点不可以重复
  • 中序遍历二叉搜索树,得到是依次递增的序列。

二、实现二叉搜索树

💦二叉搜索树的基本结构

class Node{
    public int val;
    public Node left;
    public Node right;
    public Node(int val){
        this.val = val;
    }
}

//实现二叉搜索树的基本操作
public class BinarySearchTree {
        public Node root = null;
}

🍓查找

🍎根据二叉搜索树的定义,左子树的元素比根小,右子树的元素比根大。即只需要根据根结点的值与待查找的结点的值进行比较,就能实现查找功能。

  • 根结点的值与待插入结点的值相等,表示找到了。
  • 根结点的值比待插入结点的值大,去左子树找。
  • 根结点的值比待插入结点的值小,去右子树找。
  • 左右子树找不到,就表示没有要查找的结点。

🌊代码实现

/**
 * 查找某一结点的值是否在二叉搜索树中
 * @param key 待查找的值
 * @return 如果在就返回该结点,不在就返回
 */
public Node sertchKey(int key){
    if(root==null){
        return null;
    }
    Node cur = root;
    //遍历二叉搜索树
    while (cur!=null){   //如果待查找的结点比当前结点的值大,就在该结点的右边查找
        if(cur.val<key){
            cur = cur.right;
        }else if(cur.val>key){ //如果待查找的结点比当前结点值小,就在该结点的左边查找
            cur = cur.left;
        }else { //找到了就返回该结点
            return cur; 
        }
    }
    return null; //找不到就返回null
}

🍓插入

🍎在二叉搜索树中插入一个元素,首先要找到一个合适的插入位置。利用搜索树查找的方式,找到一待插入结点的父结点。

  • 根结点的值与待插入结点的值相等,接返回false。(待插入结点的直不能与搜索树中结点的值相等)
  • 根结点的值比待插入结点的值大,去左子树找。
  • 根结点的值比待插入结点的值小,去右子树找。
  • 找到待插入结点的父结点后,创建新的结点进行插入。

🌊代码实现

/**
 * 插入结点
 * @param val 待插入结点的值
 * @return 插入成功返回 true,否则返回 false
 */
public boolean insert(int val){
    //如果是空树,就创建一个新的结点,直接插入
    if(root==null){
        root = new Node(val);
        return true; 
    }
    Node cur = root;
    Node parent = null; //用于指向待插入结点的父结点
    //遍历二叉搜索树,找到插入结点的父结点位置
    while(cur!=null){
        if(cur.val<val){ //如果待插入结点的值比当前结点的值大,就在当前结点的右边查找
            parent = cur; //指向当前结点
            cur = cur.right; //遍历当前结点的右边
        }else if(cur.val==val){ //如果待插入结点的值等于当前结点的值,就直接返回
            return false; //不能有相同的数据
        }else{ //待插入结点的值比当前结点的值小,就在当前结点的左边查找
            parent = cur;
            cur = cur.left;
        }
    }
    //找到待插入结点的父结点后进行插入
    if(val>parent.val){ //如果待插入结点的值比父结点的值大,就在父结点的右边创建一个新的结点进行插入
        parent.right = new Node(val);
    }else { //如果待插入结点的值比父结点的值小,就在父结点的左边创建一个新的结点进行插入
        parent.left = new Node(val);
    }
    return true;
}

🍓删除

💦二叉搜索树的删除操作需要考虑多种情况。

🍎设待删除结点为 cur, 待删除结点的双亲结点为 parent。需要删除结点,首先要找到待删除的结点,思路与查找的思路是一样的。

?情况1:cur.left == null

  • cur == root,让root = cur.right;
  • cur != root,parent.left == cur,让parent.left = cur.right;
  • cur != root,parent.right == cur,让parent.right = cur.right。

?情况2:cur.right == null

  • cur == null,让root = cur.left;
  • cur != root,parent.left == cur,让parent.left = cur.left;
  • cur != root,parent.right == cur,让parent.right = cur.left。

?情况3:cur.left != null && cur.right != null

  • 找到 cur 右子树中结点值最小的结点,或 cur 左子树中结点值最大的结点,使用 target 指向该结点。
  • 将 target 指向的结点的值与 cur 指向的结点的值进行替换。
  • 删除 target 指向的结点。(使用 targetParent 指向该结点的父结点)。
  • 在删除结点时要判断,target 指向的是 targetParent 的左子树还是右子树。

?🌊代码实现

/**
 * 查找待删除的结点
 * @param key
 */
public void remove(int key){
    Node cur = root;
    Node parent = null;
    while (cur!=null){
        if(cur.val>key){
            parent = cur;
            cur = cur.left;
        }else  if(cur.val<key){
            parent = cur;
            cur = cur.right;
        }else {
            //当cur指向的结点的值与待删除结点的值相同,就进行删除结点的操作
            removeNode(cur,parent);
            break;
        }
    }
}

?找 cur 右子树中结点值最小的结点

/**
 * 找到了待删除结点后,进行删除(情况三:找到右子树中最小的结点)
 * @param cur
 * @param parent
 */
public void removeNode(Node cur,Node parent){
    if(cur.left==null){  //情况一:cur.left == null
        if(cur==root){
            root = cur.right;
        }else if(cur==parent.left){
            parent.left = cur.right;
        }else { //cur==parent.right
            parent.right = cur.right;
        }
    }else if(cur.right==null){ //情况二:cur.right == null
        if(cur==root){
            root = cur.left;
        }else if(cur==parent.left){
            parent.left = cur.left;
        }else { //cur==parent.right
            parent.right = cur.left;
        }
    }else{ //情况三:cur.left != null && cur.right != null
        Node targetParent = cur;
        Node target = cur.right;
        while (target.left!=null){
            targetParent = target;
            target = target.left;
        }
        target.val = targetParent.val;
        if(target==targetParent.left){
            targetParent.left = target.right;
        }else {
            targetParent.right = target.right;
        }
    }
}

?找 cur 左子树中结点值最大的结点?

/**
 *找到了待删除结点后,进行删除(情况三:找到左子树中最大的结点)
 * @param cur
 * @param parent
 */
public void removeNode(Node cur,Node parent){
    if(cur.left==null){  //情况一:cur.left == null
        if(cur==root){
            root = cur.right;
        }else if(cur==parent.left){
            parent.left = cur.right;
        }else { //cur==parent.right
            parent.right = cur.right;
        }
    }else if(cur.right==null){ //情况二:cur.right == null
        if(cur==root){
            root = cur.left;
        }else if(cur==parent.left){
            parent.left = cur.left;
        }else { //cur==parent.right
            parent.right = cur.left;
        }
    }else{ //情况三:cur.left != null && cur.right != null
        Node targetParent = cur;
        Node target = cur.left;
        while (target.right!=null){
            targetParent = target;
            target = target.right;
        }
        target.val = targetParent.val;
        if(target==targetParent.left){
            targetParent.left = target.left;
        }else {
            targetParent.right = target.left;
        }
    }
}

四、性能分析

  • 插入和删除操作都必须先查找,查找效率代表了二叉搜索树中各个操作的性能。
  • 对有n个结点的二叉搜索树,若每个元素查找的概率相等,则二叉搜索树平均查找长度是结点在二叉搜索树的深度的函数,即结点越深,则比较次数越多。
  • 最优情况下,二叉搜索树为完全二叉树,其时间复杂度为二叉树的高度:O(\large log{_2}n)。
  • 最差情况下,二叉搜索树退化为单分支树,其时间复杂度为:O(n)。
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-04-27 11:31:56  更:2022-04-27 11:33:59 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 5:23:12-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码