二叉树查找树

二叉查找树(Binary Search Tree)

  • 二叉搜索树
  • 快速查找,插入,删除
  • 定义:每个节点,都不大于它的右子节点,且不小于它的左子节点
  • 查找:递归:大找右边,小找左边,找到或没了返回
  • 插入:递归:大找右空,不空往右;小找左空,不空往左
  • 删除
    • 先找,并记录父节点
    • 无子节点,父节点指向null
    • 一个子节点,父节点指向它
    • 2个子节点,替换和删除(右侧最小节点)
  • 排序:中序遍历,复杂度O(n),二叉排序树
  • 数据重复二叉树
    • 节点数据以链表存储
    • 插入时,相等的放右子树
  • 复杂度分析:
    • 二叉树退化成链表:O(n)
    • 平衡二叉树:O(logn),增删查
  • 对比散列表
    • 排序优势
    • 散列表存在扩容、散列冲突等,导致性能问题。平衡二叉树稳定,常用
    • 散列表较复杂,例如:散列函数设计,扩容,缩容,散列因子等
function inOrder(root) {
    let str = ''
    fn(root)
    console.log(str)
    function fn(root) {
        if (!root) return
        fn(root.left)
        str += ' ' + root.data
        fn(root.right)
    }

}

//节点
class Node {
    constructor(data) {
        this.data = data
        this.left = null
        this.right = null
    }
}

//插入
function insert(tree, data) {
    if (!tree) {
        return new Node(data)
    }
    let p = tree
    while (tree) {
        if (data >= p.data) {
            if (p.right) {
                p = p.right
            } else {
                p.right = new Node(data)
                return
            }
        } else {
            if (p.left) {
                p = p.left
            } else {
                p.left = new Node(data)
                return
            }
        }
    }
}



//查找
function find(tree, data) {
    while (tree) {
        if (data < tree.data) {
            tree = tree.left
        } else if (data > tree.data) {
            tree = tree.right
        } else {
            return tree
        }
    }
    return null
}


function del(tree, data) {
    //被删除节点父节点
    let pp
    //被删除节点
    let p = tree
    while (p && p.data != data) {
        pp = p
        if (data > p.data) {
            p = p.right
        } else {
            p = p.left
        }
    }
    if (!p) return
    //两个子节点,转化
    if (p.left && p.right) {
        let minP = p.right      //右侧最小值
        let minPP = p              //右侧最小值父节点
        while (minP.left) {
            minPP = minP
            minP = minP.left
        }
        //p和minP替换
        p.data = minP.data
        //删除minP(不删p),后面一起删,先记着
        p = minP
        pp = minPP
    }

    //小于2个子节点
    let child = p.left || p.right || null //p的子节点

    if (!pp) {          //根节点
        tree = child
    } else if (pp.left == p) { //左节点
        pp.left = child
    } else {
        pp.right = child
    }
    del(tree, data) //递归删除,直至无该数据
}


let tree = insert(null, 5)
insert(tree, 6)
insert(tree, 7)
insert(tree, 3)
insert(tree, 4)
insert(tree, 2)
insert(tree, 2)
insert(tree, 1)
insert(tree, 9)
insert(tree, 9)

inOrder(tree)
del(tree, 2)
del(tree, 9)
inOrder(tree)

insert(tree, 9)
  • 根节点高度
    • 递归:max(子树高度列表)+1
    • 队列:层次遍历,判断每层是否都完成出队

//二叉树最大高度 - 递归
function maxDepth(tree) {
    if (!tree) return 0
    return Math.max(maxDepth(tree.left), maxDepth(tree.right)) + 1
}

//二叉树最大高度 - 循环
function maxDepth1(tree) {
    if (!tree) return 0
    let queue = [tree]
    let front = 0               //队头
    let rear = queue.length     //队尾
    let floor = 0               //高度
    while (queue.length) {
        let node = queue.shift()
        front++
        if (node.left) {
            queue.push(node.left)
        }
        if (node.right) {
            queue.push(node.right)
        }
        if (front == rear) {      //进入下一层
            front = 0
            rear = queue.length
            floor++
        }
    }
    return floor
}

console.log(maxDepth(tree))
console.log(maxDepth1(tree))
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值