JS数据结构——二叉树

本文介绍了二叉树的基本概念,包括插入、查找、删除操作以及中序、先序、后序遍历。重点讨论了自平衡树——AVL树的平衡条件、高度计算、旋转操作(LL、RR、LR、RL)以及插入和删除节点的过程。此外,还提及了红黑树作为频繁插入删除场景下的优化选择。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基本二叉树

二叉树用代码实现的基本逻辑在于:自身有一个key值,以及含有左右两个节点指针(在代码中,实现起来跟链表类似)

class Node{
    this.key = key
    this.left = null
    this.right = null
    this.root = root
}

常用的方法

  1. insert(key):向树种插入一个新的键
insert(key){
    if(node.left ==null){
        node.left = new Node(key)
    }else{
     this.insert(node.left,key)   
    }
    if(node.right ==null){
        node.right = new Node(key)
    }else{
        this.insert(node.right,key)
    }
}
  1. search():查找一个数
  2. min():返回最小的值
  3. max():返回最大的值
  4. remove():移除某个值

树的遍历

中序遍历

具体规则为左-根-右

inOrderTraverseNode(node,callback){
    if(node != null){
        this.inOrderTraverseNode(node.left,callback)
        callback(node.key)
        this.inOrderTraverseNode(node.right,callback)
    }
}
先序遍历

具体规则为根-左-右

preOrderTraverseNode(node,callback){
 if(node!=null){
     callback(node.key)
     this.preOrderTraverseNode(node.left,callback)
     this.preOrderTraverseNode(node.right,callback)
 }   
}
后序遍历

具体规则左-右-根

postOrderTraverseNode(node,callback){
    if(node !=null){
        this.postOrderTraverseNode(node.left,callback)
        this.postOrderTraverseNode(node.right,callback)
        callback(node.key)
    }
}

搜索树中的值

最小值
//对于找值来说,最小值都存在树的最左下角
minNode(node){
 let current  = node
 while(current !=null && current.left != null){
     current = current.left
 }
 return current
}
最大值
//最大值存在于树的最右下角
maxNode(node){
    let current = node
    while(current !=null && current.right != null){
        current = current.right
    }
    return current 
}
特定的值
//key是需要找的值 node.key为当前节点的值
searchNode(node,key){
    if(node ==null){
        return false
    }
    if(node.key>key){
        return this.searchNode(node.left,key)
    }else if(node.key<key){
        return this.searchNode(node.right,key)
    }else{
        return ture
    }
}

删除节点

//删除前得先遍历树,找到需要删除的值
removeNode(node,key){
    if(node ==null){
        return null
    }
    if(node.key>key){
        node.left = this.removeNode(node.left,key)
        return node
    }else if(node.key<key){
         node.right = this.removeNode(node.right,key)
         return node
    }else{
        //分为三种情况,第一种情况直接移除一个叶子节点
        if(node.left ==null && node.right==null){
            node = null
            return node
        }
        //第二种情况,移除一个有一边节点的节点,此时需要将父节点直接指向该节点的子节点即可
        if(node.left ==null){
            node = node.right
            return node
        }else if(node.right ==null){
            node = node.left
            return node
        }
        第三种情况,移除一个拥有两个子节点的节点,此时需要找到该节点中最小的节点,将该节点的值替换到需要删除的节点中,并把最小的节点删除
        const changemin = this.minNode(node.right)
        node.key = changemin.key
        node.right= this.remove(node.right,key)
        return node
    }
}

自平衡树

任何一个节点左右两侧子树的高度差最多为1

计算高度
getNodeHeight(node){
    if(node ==null){
        retuen -1
    }
    return Math.max(
    this.getNodeHeight(node.left),this.getNodeHeight(node.right)
    )
}

在AVL树中要计算右子树高度和左子树高度的差值(hr-hl),结果只能是0,-1,1,如果不是这三个值,就需要平衡

const BalanceFactor{
    UNBALANCED_RIGHT:1,
    SLIGHTLY_UNBALANCED_RIGHT:2,
    BALANCED:3,
    SLIGHTLY_UNBALANCED_LEFT:4,
    UNBALANCED_LEFT:5
}
getBalanceFactor(node){
    const heightDifference = this.getNodeHeight(node.left) -this.getNodeHeight(node.right)
    switch(heightDifference){
        case -2:
        return BalanceFactor.UNBALANCED_RIGHT;
        case -1:
        return BalanceFactor.SLIGHTLY_UNBALANCED_RIGHT;
        case 1:
        return BalanceFactor.SLIGHTLY_UNBALANCED_LEFT
        case 2:
        return BalanceFactor.UNBALANCED_LEFT
        default:
        return BalanceFactor.BALANCED
    }
}
平衡操作(AVL旋转)
左-左(LL)向右的单旋转

左侧节点的高度 大于 右侧子节点的高度,并且左侧子节点也是平衡或者左侧较重的

rotationLL(node){
    const tmp = node.left
    node.left = tmp.right
    tmp.right = node
    return tmp
}
右-右(RR)向左的单旋转

右侧节点的高度 大于 左侧子节点的高度,并且左侧子节点也是平衡或者右侧较重的

rotationRR(node){
    const tmp = node.right
    node.right = tmp.left
    tmp.left = node
    return tmp
}
左-右(LR)向右的双旋转(先LL旋转,再RR旋转)

左侧节点的高度 大于 右侧子节点的高度,并且左侧子节点右侧较重,因此先左旋转修复,再对不平衡的节点右旋转修复

rotationLR(node){
   node.left = this.rotationRR(node.left)
   return this.rotationLL(node)
}
右-左(RL)向左的双旋转(先RR旋转,再LL旋转)

右侧节点的高度 大于 左侧子节点的高度,并且右侧子节点左侧较重

rotationRL(node){
   node.right = this.rotationLL(node.right)
   return this.rotationRR(node)
}
在AVL树中插入节点
在AVL树中移除节点

红黑树

红黑树跟AVL树类似,但是如果多次进行插入和删除,红黑树是更好的选择

  1. 每个节点不是红的就是黑的
  2. 根节点是黑的
  3. 所有叶节点都是黑的(NULL引用表示的节点)
  4. 如果一个节点是红的,他的两个叶子节点都是黑的
  5. 不能有两个相邻的红节点,一个红节点不能有红的父节点或者子节点
  6. 从给定的节点到它的后代节点的所有路径包含相同数量的黑色节点
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值