Javascript数据结构与算法学习(六)—— 树

树结构

树是一种重要的非线性数据结构,直观地看,它是数据元素(在树中称为结点)按分支关系组织起来的结构,很象自然界中的树那样。

  • HTML结构就是典型的树结构
    在这里插入图片描述

二叉搜索树

  • 特点:
    • 节点最多只能有两个子节点,一个左子节点,一个右子节点,左右子节点的顺序不能颠倒。
    • 在左侧存储比父节点小的值
    • 在右侧存储比父节点大的值
  • 实现:
    • 树(Tree)有:根节点,内部的Node类,查找,删除,插入,遍历
      在这里插入图片描述
  • 插入节点
function Tree(){
 	var Node = function(val){
        this.value = val
        this.left = null
        this.right = null
    }

    var root = null
    //  插入节点
    /**
     * 1、树为空树:root = value
     * 2、树不是空的:对比节点
     */
    var insertNode = function(node,newNode){
        if(newNode.value>node.value){
            if(node.right===null){
                node.right = newNode
            }else{
                insertNode(node.right,newNode)
            }
        }else if(newNode.value<node.value){
            if(node.left===null){
                node.left = newNode
            }else{
                insertNode(node.left,newNode)
            }
        }
    }
    this.insert = function(value){
        var node = new Node(value)
        if(root===null){
            root = node
        }else{
            insertNode(root,node)
        }
    }
}

  • 遍历树
  • 先序遍历:根节点最先被遍历,从上往下,从左往右遍历
  • 中序遍历:根节点在中间时间被遍历,可以从小到大按顺序打印
  • 后序遍历:根节点最后被遍历,从下往上,从左往右遍历,从树左边最后一个节点开始遍历,依次先遍历末尾节点再往上
    在这里插入图片描述

 // 遍历节点
  // 借助递归
    function traverse(node, callback){
        if(node===null) return;
        traverse(node.left,callback)
        traverse(node.right,callback)
        callback(node.value)
    }
    this.traverse = function(callback){
        traverse(root,callback)
    }
  • 获取最小值
    在这里插入图片描述
  • 移除节点

移除节点有很多种情况:

  1. 移除有2个子节点的?——选哪个子节点来代替被删除的节点
  2. 移除末位节点(叶节点):node.leftnull, node.rightnull的情况
  3. 移除只有1个子节点
  • 移除节点的方法
  1. 原理:重新构建树
  2. 方法:每次以右侧子树的最小节点来替换被删除的节点
    在这里插入图片描述
/**
 * 根节点 root
 * 插入 insert
 * 查找 search
 * 遍历 traverse
 * 删除 remove
 * 内部的Node类
 * 
 */
function Tree(){
    var Node = function (value){
        this.value = value
        this.left = null
        this.right = null
    }
    var root = null
    // 插入
    function insert(node,newNode){
        if(node.value<newNode.value){
            if(node.right===null){
                node.right = newNode
            }else{
                insert(node.right,newNode)
            }
        }else{
            if(node.left===null){
                node.left = newNode
            }else{
                insert(node.left,newNode)
            }
        }
    }
    this.insert = function(value){
        var node = new Node(value)
        if(!root){
            root = node
        }else{
            insert(root,node)
        }
    }
    // 搜索
    var searchNode = function(node,value){
        if(node===null) return null
        if(value<node.value) return searchNode(node.left,value)
        else if(value>node.value) return  searchNode(node.right,value)
        else return node
    }
    this.search = function(val){
        searchNode(root,value)
    }
    // 遍历
    function traverse (node,callback){
        if(!node) return;
        //  callback(node.value) //前序遍历 —— 访问根节点的操作发生在遍历其左右子树之前。
        traverse(node.left,callback)
        // callback(node.value) //中序遍历 —— 访问根节点的操作发生在遍历其左右子树之间。
        traverse(node.right,callback)
        callback(node.value) //后序遍历 —— 访问根节点的操作发生在遍历其左右子树之后
    }
    this.traverse = function(callback){
        traverse(root,callback)
    }
    // 最小值
    this.min = function(node){
        if(node===null) return null;
        while(node&&node.left!==null){
            node = node.left
        }
        return node
    }
    // 最大值
    this.max = function(node){
        if(node===null) return null
        while(node&&node.right!==null){
            node = node.right
        }
        return node
    }
    // 辅助方法,用于查找最小节点
    function findMinNode(node){
        if(node === null) return null
        while(node && node.left!== null){
            node = node.left
        }
        return node
    }
    // 删除——重新构建树
     //  移除节点
    function removeNode(node, value) {
        if (node === null) return null
        
        // 叶节点
        if (value > node.value) {
            // 向右查找
            node.right = removeNode(node.right, value)
            return node
        } else if (value < node.value) {
            // 向左查找
            node.left = removeNode(node.left, value)
            return node
        } else {
            // 情况一:没有子节点
            if (node.left == null && node.right == null) {
                node = null
                return node
            }
        }

        // 情况二:只有一个子节点
        if (node.left == null && node.right) {
            return node.right
        } else if (node.right == null && node.left) {
            return node.left
        }

        // 情况三:有两个子节点
        function findMinNode(node) {
            if (node == null) return null
            while(node && node.left!== null){
                node = node.left
            }
            return node
        }
        var aux = findMinNode(node) // 查找右侧最小子节点
        node.value = aux.value
        node.right = removeNode(node.right,aux.value)
        return node
    }
    this.remove = function (key) {
        root = removeNode(root,key) //重新构建树
    }
    this.getTree = function(){
        return root
    }
}
var t = new Tree

t.insert(8)
t.insert(2)
t.insert(3)
t.insert(9)

// t.remove(2)
// console.log(t.getTree())
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sophie_U

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值