js 删除节点_js实现二叉搜索树

最近在学习数据结构和算法,所以用js来实现一下二叉搜索树,检验学习效果。

首先,我们来简单说一下什么是二叉搜索树,它有什么特性:

二叉搜索树(二叉查找树)不同于普通二叉树,是它的左子树所有的节点都小于根节点,右子树所有的节点都大于根节点,并且其左右子树也是二叉搜索树。

12ffc2a684b935e14c13597073f288cf.png
图丑也可以看

二叉搜索树的概念不多说,具体来看看js代码:

0abc2c9dcb883bb3209477be96d4823e.png
二叉搜索树类

上图,写了一个二叉搜索树的类,用来生成二叉搜索树的实例;可以看到,类里面只有一个root属性来保存根节点,然后还有一些操作方法;下面我们来看看每个方法怎么实现。

插入方法:

0ddb461defd9c4419f49ef627d6c1a0b.png
插入方法

3a2684c23f20c8c0ff9643a4154146a0.png
节点构造函数

因为插入需要创建新节点,所以写了一个简单的节点构造函数,函数内有三个属性,key:表示节点的关键字也是值,left:指向左子树,right:指向右子树。

插入新节点的流程也比较简单,就是先创建一个节点,然后根据插入节点的大小,遍历找到插入的位置,然后赋值插入就OK;遍历之前需要先判断根节点是否有值,没有则直接赋值,然后返回。

遍历方法:

遍历二叉树的方法主要有:先序遍历、中序遍历、后续遍历三种;

先序遍历:先访问根节点,再遍历左子树,最后遍历右子树,在遍历左、右子树的过程中依然采用先序遍历。(先根再左后右)

中序遍历:先遍历左子树,再访问根节点,最后遍历右子树,在遍历左、右子树的过程中依然采用中序遍历。(先左后根再右)

后序遍历:先遍历左子树,再遍历右子树,最后访问根节点,在遍历左、右子树的过程中依然采用后序遍历。(先左后右再根)

df2017269bc0224edb19f9222af8f753.png
先序遍历方法

如上代码,是采用递归来实现遍历,可以看到,先序遍历是将处理节点的回调函数放在了最前面,这也意味着函数入栈时就处理节点,所以处理的顺序是:9-5-4-3-7-6-8-13-11-10-12-14

eacc213867d4af07fa9b7fa79ecec24e.png
中序遍历方法

可以看到,中序遍历是将处理节点的回调放到了遍历左子树的后面,这样就意味着在遍历左子树的函数出栈后再处理节点(这里需要理解函数调用栈,栈结构只能在栈顶进出,所以函数执行的顺序是先进后出),所以处理节点的顺序是:3-4-5-6-7-8-9-10-11-12-13-14

可以发现,中序遍历将整个二叉搜索树进行了从小到大的排序。

9de04a128926b2343e4f4ac68f2151cd.png
后序遍历方法

看到这里,后序遍历也很容易理解了,就是将处理的回调函数放在最后,等遍历右子树的函数出栈后再处理节点;所以处理节点的顺序是:3-4-6-8-7-5-10-12-11-14-13-9

获取最大值、最小值:

6e4a24c2ddbc1adb04a5568eb6ac6e58.png

搜索节点:

4a001cf9233170a4753f65a6ff156c3c.png

删除节点:

删除节点的操作比较复杂,这里分几个阶段来说:

1.首先,找到要删除的节点

be63230898c22fed957fb416654f6735.png

这里说明一下函数开头声明的几个变量,current用来存储要删除的节点,parentNode存储删除节点的父节点,isLefChi用来区分删除节点是父节点的左子节点还是右子节点。

2.根据要删除节点的不同情况进行删除

2.1 删除节点为叶节点

8d6fd0861632ea5024d76cca4b0a876d.png

2.2 删除节点只有一个子节点

2484d998f65827e6590211ac4ddb1f4f.png

只有一个节点的情况,需要再次判断是没有左子节点,还是没有右子节点;

2.3 删除节点有两个子节点

606a35f3817f10fbf500d88e92fe6d48.png

说一下前驱和后继:

1)删除节点有两个子节点,这两个子节点下面也许还有子节点(子节点树);

2)我们需要从子节点树中找一个节点来替换删除节点;

3)根据二叉搜索树的特性:左子树小于根节点,右子树大于根节点,左右子树亦如此,可以发现,最适合用来替换(也可以说大小最接近)删除节点的有两个,一个是删除节点左子树最大节点(前驱),还有一个是右子树最小节点(后继),用其他的节点都不满足二叉搜索树的特性;

4)遍历找到前驱/后继节点(哪一个都行);

5)这里也有个情况要注意,前驱节点是否是删除节点的直接子节点;

好了,到这里就完成了js版的二叉搜索树。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值