[数据结构] 二叉搜索树基本操作

img

定义

二叉搜索树是一种特殊的二叉树,其定义如下:

  1. 空树是二叉搜索树。
  2. 若二叉搜索树的左子树不为空,则其左子树上所有点的附加权值均小于其根节点的值。
  3. 若二叉搜索树的右子树不为空,则其右子树上所有点的附加权值均大于其根节点的值。
  4. 二叉搜索树的左右子树均为二叉搜索树。

操作

CRUD

二叉搜索树的基本操作有:查询、新增、删除;

这些操作的最优时间复杂度为 \(O(\log n)\) ,最坏时间复杂度为 \(O(n)\),随机构建的二叉搜索树的期望高度为 \(O(\log n)\)

遍历

根据二叉搜索树的定义可知:二叉搜索树的中序遍历结果是非降序序列

遍历二叉搜索树的时间复杂度是 \(O(n)\)

let arr = [];
function traverse(root){if(root==null)return;traverse(root.left);arr.push(root.val);traverse(root.right);
}
traverse(root);
console.log(arr);

查找最值

  • 最小值为二叉搜索树最左边的节点;
  • 最大值为二叉搜索树最右边的节点。
function findMinNode(root){while(root.left!==null){root = root.left;}return root;
}function findMaxNode(root){while(root.right!==null){root = root.right;}return root;
}

搜索

递归搜索,分类讨论:

  • root为空,则已到达叶子节点,找不到指定值;
  • root的值为target,则搜索到目标值;
  • root的值大于target,则在root的左子树中继续搜索;
  • root的值小于target,则在root的右子树中继续搜索。
function search(root, target){if(root==null)return null;if(root.val == target){return root;}else if(target < root.val){return search(root.left, target);}else{return search(root.right, target);}
}

插入一个元素

flowchart TDid1((30)) --> id2((15)) & id3((41))id3((41)) --> id4((35)) & id5((48))id4((35)) --> id6((33)) & id7((36))

在以 root 为根节点的二叉搜索树中插入一个值为 value 的节点。

分类讨论:

  • root为空,直接返回一个值为value的新节点;
  • 如果root的值等于value,表示元素已存在,根据应用场景做相关处理(有的设计是节点的count属性+1,有的设计是不做处理);
  • 如果root的值大于value,则在root的左子树中插入值为value的节点;
  • 如果root的值小于value,则在root的右子树中插入值为value的节点。
function insert(root, value){if(root==null)return new TreeNode(value);if(root.val > value){root.left = insert(root.left, value);}else if(root.val < value){root.right = insert(root.right, value);}else{// root.val == value}return root;
}

删除一个元素

flowchart TDid1((30)) --> id2((15)) & id3((41))id3((41)) --> id4((35)) & id5((48))id4((35)) --> id6((33)) & id7((36))

在以 root 为根节点的二叉搜索树中删除一个值为 value 的节点。

分类讨论:

  • root为叶子节点,则直接删除;
  • root只有一个子节点,则返回这个子节点;
  • root有两个子节点,一般用右子树的最小值代替它,然后将它删除。(具体的操作是将右子树的最小值赋值给它,然后去右子树中递归删除这个值,完成“代替”)
function remove(root, value){if(root==null)return null;if(value < root.val){// 在左子树中搜索并删除目标节点root.left = remove(root.left, value);return root;}else if(value > root.val){// 在右子树中搜索并删除节点root.right = remove(root.right, value);return root;}else{// 找到节点了// case 1: 叶子节点if(root.left==null && root.right==null){root = null;return root;}// case 2: 一个子节点if(root.left==null){return root.right;}else if(root.right==null){return root.left;}// case 3: 两个子节点const findMinNode = (root)=>{while(root.left!==null){root = root.left;}return root;}const rightMin = findMinNode(root.right);root.val = rightMin.val;root.right = remove(root.right, rightMin.val);return root;}
}

题外话——Mermaid

Mermaid官方文档:流程图语法 | Mermaid 中文网 (nodejs.cn)

最近发现一个在Markdown里画图挺好用的工具,比如上面的二叉树就是用Mermaid画的,可以用指令实现一些简单的图表绘制。

比如下面这段指令:

flowchart TDid1((30)) --> id2((15)) & id3((41))id3((41)) --> id4((35)) & id5((48))id4((35)) --> id6((33)) & id7((36))
  • flowchart:流程图;
  • TD:从上到下的绘制方向;
  • id*:标识符,和变量名一个道理;
  • ((val))val是节点中的值,(())表示圆形,[]表示矩形;
  • -->:箭头,==>更粗的箭头;
  • &:表示语句的组合,如果没有这个&,则需要编写两行指令分别表示左右子节点的配置。

效果图

flowchart TDid1((30)) --> id2((15)) & id3((41))id3((41)) --> id4((35)) & id5((48))id4((35)) --> id6((33)) & id7((36))

参考文章

[1] 二叉搜索树 & 平衡树 - OI Wiki

[2] 二叉搜索树_百度百科 (baidu.com)

[3] 数据结构——二叉搜索树详解-CSDN博客

[4] 流程图语法 | Mermaid 中文网 (nodejs.cn)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/741434.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

014 批处理系统

写在前面 本随笔是非常菜的菜鸡写的。如有问题请及时提出。 可以联系:1160712160@qq.com GitHhub:https://github.com/WindDevil (目前啥也没有 本章目的保障系统安全 多应用支持本章需要实现的新功能构造包含操作系统内核和多个应用程序的单一执行程序 通过批处理支持多个程…

DOM属性

常用 DOM 属性innerHTML:用于获取或设置元素的 HTML 内容。 可以直接插入 HTML 代码,适合处理复杂的 HTML 结构。element.innerHTML = <p>New content</p>; console.log(element.innerHTML);innerText:用于获取或设置元素的文本内容,只包括可见的文本。 会触发重…

【一天一点.NET小知识】运用向量VectorT加速求和计算

随着 .NET 版本的演进,从 .NET Standard 2.0 版本开始,支持 Vector<T> 类型。 Vector<T> 类型:表示指定数值类型(适用于并行算法的低级别优化)的单个向量。 假如我们有一个求和函数接受一个int数组入参,当它的长度大于等于8及其倍数以上时,那么我们就可以考…

实战篇——CSRF漏洞pikachu靶场实战

实战篇——CSRF漏洞pikachu靶场实战 CSRF的原理 攻击者利用用户在某个网站上的已登录状态,诱使用户点击恶意链接,恶意页面会向服务器自动发送预先准备好的恶意请求。由于请求中自动包含了用户的认证凭证,服务器会误以为是合法的用户操作,从而执行恶意请求。 CSRF的分类 (1)…

Bulldog_2 靶机提权

一、目标环境 攻击者(kali)、目标服务器(ubuntu) 二、信息收集 1、探测靶机 使用fscan进行探测 ./fscan -h ip 段发现目标地址,并且还发现对方开启了80端口 三、目标站点的访问以及检测然后发现两个接口,分别是登陆和注册的然后就是在登陆接口这边尝试一下弱口令发现并不…

PySimpleGUI笔记

本博客详细介绍了 PySimpleGUI 的基本用法和高级功能,并通过实际案例演示了如何使用 PySimpleGUI 开发图形用户界面 (GUI) 应用。主要内容包括:基本用法:介绍了 PySimpleGUI 的基本组件和窗口创建方法,通过简单示例展示了如何创建和管理窗口。 事件处理:讲解了如何处理用户…

忆 2015 硅谷之行

2015 硅谷之行 ,是我脑海里一段充满海蓝色的记忆。 有点像刘姥姥进大观园,也有点像进入另外一个我不曾幻想过的世界。 郊区很美 我们住在郊区,人很少,景色很美。每次去吃饭,还得驱车 15 分钟左右去附近最近的餐厅。Google 总部 Google 对于每个程序员来讲,都是一个梦幻的…

py并发编程

并发编程(并发,并行,同步,异步) 通俗理解并发编程中的相关核心概念 核心概念:进程、线程CPU的作用计算机的核心是CPU,它承担了所有的计算任务。它就像一座工厂,时刻在运行。 CPU的核数(多核计算机多个CPU,大部分情况下也只是用了一核CPU)假定工厂的电力有限,一次只…

Android studio导出apk文件

在Android studio中打开项目 选择build——》 build bundle(s)/apk(s)——》build apk(s) 加载完成后点击右下角弹窗的local(或者在  项目地址\app\build\outputs\apk\debug  中找到apk文件) 将apk文件复制到对应设备上就可以啦(最好别用qq)

JDK、JRE、JVM

JDK:Java Development Kit JRE: Java Runtime Environment JVM: Java Virtual Machine

[CINTA] 具体数论与代数阅读笔记——第一章 整数和二进制(含加、乘、除)

这里是王立斌老师的《具体数论与代数》(CINTA)的阅读笔记前言 这本书说自己是计算机专业数学入门之入门,成为读者攻读其他经典著作的垫脚石,但个人以为足矣替换掉本校内不知所云的、抽象的、让学生考完后马上全忘的那些课程。本书的 GitHub 仓库在这里。 该笔记并非单纯的整…

热爱无限

青春不在年华,而在心境;青春不是桃面、丹唇、柔膝,而是深沉的意志、恢弘的想象、炙热的情感,更是生命中无限的热爱。它使你有一台天线,从天上接受着勇气与力量的信号,使你青春永驻。 怀揣着热爱,我投入到无限的学习之中。当我第一次接触信息学竞赛时,就被其中无限的知识…