树 --js

1 二叉搜索树

function BinarySearchTree(){
  // 初始化节点
  var Node = function(key){
    this.key = key
    this.left = null
    this.right = null
  }
  // 初始化root
  let root = null
  this.insert = function (key) {
    let newNode = new Node(key)
    if(root === null){
       root = newNode
    } else {
       // 如果root有值,则试着插入他的子节点
        insertNode(root, newNode)
      }
  }
  function insertNode(f,s) {
      if (s.key<f.key) {
          if (!f.left) {
            f.left = s
          } else {
            insertNode(f.left, s)
          }
      }else{
         if (!f.right) {
           f.right = s
         } else {
            insertNode(f.right, s)
         }
      }
  }
  this.getRoot = function(){
      console.log(root)
    }
}
var tree = new BinarySearchTree()
tree.insert(11)
tree.insert(7)
tree.insert(15)
tree.insert(5)
tree.insert(3)
tree.insert(9)
tree.insert(8)
tree.insert(10)
tree.insert(13)
tree.insert(12)
tree.insert(14)
tree.insert(20)
tree.insert(18)
tree.insert(25)
tree.getRoot()

2 遍历

2.1 中序遍历
概念:是一种以上行顺序访问BST所有节点的遍历方式,也就是以从最小到最大的顺序访问所有节点。

function printNode(value) {
    console.log(value)
}
---BST内部---
  this.inOrderTraverse = function (callback) {
    inOrderTraverseNode(root,callback)
  }
  inOrderTraverseNode = function (node, callback) {
      if (node !== null) {
          console.log('top', node.key)
          inOrderTraverseNode(node.left, callback)// 
          callback(node.key) // 
          inOrderTraverseNode(node.right, callback)// 
          console.log('bottom', node.key)
      }
  }

1,第一步:
会一直向左寻找 11 7 5 3
找到node.key === 3后递归结束,执行当前函数的剩余代码
3没有right当前函数执行结束
2,第二步
执行5剩余的代码
输出5
node.key === 5

function BinarySearchTree(){
  // 节点
  var Node = function(key){
    this.key = key
    this.left = null
    this.right = null
  }
  let root = null
  this.insert = function (key) {
    let newNode = new Node(key)
    if(root === null){
       root = newNode
    } else {
        insertNode(root, newNode)
      }
  }
  this.inOrderTraverse = function (callback) {
    inOrderTraverseNode(root,callback)
  }
  inOrderTraverseNode = function (node, callback) {
      if (node !== null) {
          console.log('top', node.key)
          inOrderTraverseNode(node.left, callback)// 会一直向左寻找 11 7 5 3
          callback(node.key) // 找到3后递归结束,执行当前函数的剩余代码
          inOrderTraverseNode(node.right, callback)// 3没有没有right当前函数执行结束
          console.log('bottom', node.key)
      }
  }

  function insertNode(f,s) {
      if (s.key<f.key) {
          if (!f.left) {
            f.left = s
          } else {
            insertNode(f.left, s)
          }
      }else{
         if (!f.right) {
           f.right = s
         } else {
            insertNode(f.right, s)
         }
      }
  }
  this.getRoot = function(){
      console.log(root)
    }
}
// 中序遍历

function printNode(value) {
    console.log(value)
}
var tree = new BinarySearchTree()
tree.insert(11)
tree.insert(7)
tree.insert(15)
tree.insert(5)
tree.insert(3)
tree.insert(9)
tree.insert(8)
tree.insert(10)
tree.insert(13)
tree.insert(12)
tree.insert(14)
tree.insert(20)
tree.insert(18)
tree.insert(25)
tree.insert(6)
tree.inOrderTraverse(printNode)

2.1先序遍历
概念:先访问节点本身,然后再会访问左侧子节点,最后是右侧节点。

 preOrderTraverseNode = function (node, callback) {
      if (node !== null) {
         callback(node.key) 
          preOrderTraverseNode(node.left, callback)
          preOrderTraverseNode(node.right, callback)
      }
  }

2.3 后序遍历
概念:先访问节点的后代节点,再访问节点。
应用:计算目录和子目录所有文件所占空间的大小

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

第一步:
从root ===11开始
一直执行post(node.left)直到执行到node.key ===3 print:3
在5的环境下,向下执行代码,print: 6
print 5,退出5的环境
第二步
node.left.key ===5
执行node.right.key===9
print的顺序与第一步类似
print: 8 10 9
第三步
print 7
第四步
类似于第二步
print: 12 14 13 18 25 20 15
所以总的是
3 6 5 8 10 9 12 14 13 18 25 20 15 11

3 搜索树中的值

3.1搜索最大值

 // 最小值
  this.min = function(){
    return minNode(root)
  }
  function minNode(node){
    if(node){
      while(node.left!==null){
        node = node.left
      }
      return node.key
    }
    return null
  }

3.2搜索最小值

 // 最大值
  this.max = function(){
    return maxNode(root)
  }
  function maxNode(node){
    if(node){
      while(node.right!==null){
        node = node.right
      }
      return node.key
    }
    return null
  }

3.3搜索特定值

  // 和has 方法类似
  this.search = function(key){
    return searchNode(root,key)
  }
  function searchNode(node,key){
    if (node === null) {
      return false
    }
    if (node.key>key) {
      return searchNode(node.left,key)  

    } else if(node.key<key) {
      return searchNode(node.right,key) 
    } else {
      return true
    }

  }

console.log(tree.search(100))
分析:
1 root.key ===11 , key ===100
searchNode(node.right.key=15,100)
100与node.key的关系只会是三种大于,小于或者等于
node.key<100 右边找 return search(node.right)// 不管存在不存先赋值了再说,如果node.right === null则搜索结束,不为null可能进行与之前一样的判断,一直找到最后一个node.left或者right实际是不存在的。
node.key>100 左边找 return search(node.left)//左边的也是类似
以上两种都不是则node.key ===100
console.log(tree.search(1))
console.log(tree.search(9))

4 移除某个节点

 this.remove = function(key){
    root = removeNode(root,key)
  }
  var removeNode = function(node,key){
    if(node === null){
      return null
    }
    if(key<node.key){
      node.left = removeNode(node.left,key)
      return node
    }else if(key>node.key){
      node.right = removeNode(node.right,key)
      return node
    }else{
      // 第一种情况 一个叶节点
      if(node.left === null&& node.right === null){
        node = null
        return node
      // 第二种情况 一个只有一个子节点的节点  
      }else if(node.left === null){
        node = node.right
        return node
      }else if(node.right === null){
        node = node.left
        return node
      }
      // 第三种情况 一个有两个子节点的节点
      var aux = (function findMinNode(node){
        while(node&&node.left!==null){
          node = node.left
        }
        return node
      })(node.right)
      node.key = aux.key
      node.right = removeNode(node.right,aux.right)
      return node
    }
  }

分析:
情况1:tree.remove(3)
root = removeNode(root,3)
进入key<node.key的条件里面
node.left = removeNode(,3)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容