js-js数据结构和算法-树

树是一种分层数据的抽象模型
一个树结构包含一系列存在父子关系的节点。每个节点都有一个父节点(除了顶部的第一个
节点)以及零个或多个子节点:
根节点:位于树顶部的节点叫作根节点。它没有父节点。树中的每个元素都叫作节点,节点分为内部节点和外部节点。一个节点可以有祖先和后代。
内部节点:至少有一个子节点的节点称为内部节点。
外部节点或叶节点:没有子元素的节点称为外部节点或叶节点
子树:由节点和它的后代构成
深度:节点的深度取决于它的祖先节点的数量
高度: 树的高度取决于所有节点深度的最大值
二叉树: 二叉树中的节点最多只能有两个子节点:一个是左侧子节点,另一个是右侧子节点
二叉搜索树: 二叉搜索树(BST)是二叉树的一种,但是它只允许你在左侧节点存储(比父节点)小的值,
在右侧节点存储(比父节点)大(或者等于)的值。
边:通过指针来表示节点之间的关系。
键: 树相关的术语中对节点的称呼
根元素:第一个节点

insert(key):向树中插入一个新的键。
 search(key):在树中查找一个键,如果节点存在,则返回true;如果不存在,则返回
false。
 inOrderTraverse:通过中序遍历方式遍历所有节点。
 preOrderTraverse:通过先序遍历方式遍历所有节点。
 postOrderTraverse:通过后序遍历方式遍历所有节点。
 min:返回树中最小的值/键。
 max:返回树中最大的值/键。
 remove(key):从树中移除某个键

遍历

中序
从小到大
排序

先序
父子顺序
打印结构

后序
子父顺序
目录空间大小

最大最小值
特定值
移除节点

其他树

BST树:取决于你添加的节点数,树的一条边可能会非常深;也就是说,树的一
条分支会有很多层,而其他的分支却只有几层
红黑树:高效中序遍历
推积树:
AVL树:阿德尔森-维尔斯和兰迪斯树,自平衡二叉搜索树

et 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)
    }
  }
  let insertNode = function(node, newNode) {
    if(newNode.key < node.key) {
      if(node.left === null) {
        node.left = newNode
      } else {
        insertNode(node.left, newNode)
      }
    } else {
      if(node.right === null) {
        node.right = newNode
      } else {
        insertNode(node.right, newNode)
      }
    }
  }
  // 中序遍历
  this.inOrderTraverse = function(cb) {
    inOrderTraverseNode(root, cb)
  }
  let inOrderTraverseNode = function(node, cb) {
    if(node !== null) {
      inOrderTraverseNode(node.left, cb)
      cb(node.key)
      inOrderTraverseNode(node.right, cb)
    }
  }
  // 先序
  this.preOrderTraverse = function(cb) {
    preOrderTraverseNode(root, cb)
  }
  let preOrderTraverseNode = function(node, cb) {
    if(node !== null) {
      cb(node.key)
      preOrderTraverseNode(node.left, cb)
      preOrderTraverseNode(node.right, cb)
    }
  }
  // 后序
  this.postOrderTraverse = function(cb) {
    postOrderTraverseNode(root, cb)
  }
  let postOrderTraverseNode = function(node, cb) {
    if(node !== null) {
      postOrderTraverseNode(node.left, cb)
      postOrderTraverseNode(node.right, cb)
      cb(node.key)
    }
  }
  // 最小值
  this.min = function() {
    return minNode(root)
  }
  let minNode = function(node) {
    if(node) {
      while(node.left !== null) {
        node = node.left
      }
      return node.key
    }
    return null
  }
  // 最大值
  this.max = function() {
    return maxNode(root)
  }
  let maxNode = function(node) {
    if(node) {
      while(node.right !== null) {
        node = node.right
      }
      return node.key
    }
    return null
  }
  // 特定值
  this.search = function(key) {
    return searchNode(root, key)
  }
  let searchNode = function(node, key) {
    if(node === null) {
      return false
    }
    if( key < node.key){
      return searchNode(node.left, key)
    } else if( key > node.key){
      return searchNode(node.right, key)
    } else {
      return true
    }
  }
  // 移除
  this.remove = function(key) {
    root = removeNode(root, key)
  }
  let 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
      }
      // 只有一个子节点
      if(node.left === null) {
        node = node.right
        return node
      }else if(node.right === null) {
        node = node.left
        return node
      }
      // 两个子节点
      let aux = findMinNode(node.right)
      node.key = aux.key
      node.right = removeNode(node.right, aux.key)
      return node
    }
  }
  let findMinNode = function(node) {
    if(node) {
      while(node.left !== null) {
        node = node.left
      }
      return node
    }
    return null
  }
}
let printNode = function(v) {
  console.log(v)
}
var tree = new BinarySearchTree();
tree.insert(11);
tree.insert(7);
tree.insert(15);
tree.insert(6);
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.inOrderTraverse(printNode) // 顺时针 左上右
// 3 5 6 7 8 9 10 11 12 13 14 15 18 20 25 --- 
console.log(`---`)
tree.preOrderTraverse(printNode) // 逆时针 上左右
// 11 7 5 3 6 9 8 10 15 13 12 14 20 18 25 ---
console.log(`---`)
tree.postOrderTraverse(printNode) // 逆时针 左右上
// 3 5 6 8 10 9 7 12 14 13 18 25 20 15 11  ---
console.log(`---`)
console.log(`tree.min()`, tree.min())
console.log(`tree.max()`, tree.max())
console.log(`tree.search()`, tree.search(3))
console.log(`tree.remove()`, tree.remove(3))
console.log(`---`)
tree.inOrderTraverse(printNode)
console.log(`---`)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值