女王控的博客

树的遍历算法与深度拷贝函数

广度优先搜索

以二叉树的层次遍历举例:

/*
 * @lc app=leetcode.cn id=102 lang=javascript
 *
 * [102] 二叉树的层次遍历
 *
 * https://leetcode-cn.com/problems/binary-tree-level-order-traversal/description/
 *
 * algorithms
 * Medium (53.64%)
 * Total Accepted:    17.4K
 * Total Submissions: 32.4K
 * Testcase Example:  '[3,9,20,null,null,15,7]'
 *
 * 给定一个二叉树,返回其按层次遍历的节点值。 (即逐层地,从左到右访问所有节点)。
 * 
 * 例如:
 * 给定二叉树: [3,9,20,null,null,15,7],
 * 
 * ⁠   3
 * ⁠  / \
 * ⁠ 9  20
 * ⁠   /  \
 * ⁠  15   7
 * 
 * 
 * 返回其层次遍历结果:
 * 
 * [
 * ⁠ [3],
 * ⁠ [9,20],
 * ⁠ [15,7]
 * ]
 * 
 * 
 */
/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[][]}
 */
var levelOrder = function(root) {
    if (!root) {
      return [];
    }
    const queue = [root];
    const results = [];
    while (queue.length) {
      let count = queue.length;
      const result = [];
      while (count--) {
        const t1 = queue.shift();
        result.push(t1.val);
        t1.left && queue.push(t1.left);
        t1.right && queue.push(t1.right);
      }
      results.push(result);
    }
    return results;
};

深度优先搜索

/*深度优先遍历三种方式*/
let deepTraversal1 = (node, nodeList = []) => {
  if (node !== null) {
    nodeList.push(node)
    let children = node.children
    for (let i = 0; i < children.length; i++) {
      deepTraversal1(children[i], nodeList)
    }
  }
  return nodeList
}
let deepTraversal2 = (node) => {
    let nodes = []
    if (node !== null) {
      nodes.push(node)
      let children = node.children
      for (let i = 0; i < children.length; i++) {
        nodes = nodes.concat(deepTraversal2(children[i]))
      }
    }
    return nodes
  }
// 非递归
let deepTraversal3 = (node) => {
  let stack = []
  let nodes = []
  if (node) {
    // 推入当前处理的node
    stack.push(node)
    while (stack.length) {
      let item = stack.pop()
      let children = item.children
      nodes.push(item)
      // node = [] stack = [parent]
      // node = [parent] stack = [child3,child2,child1]
      // node = [parent, child1] stack = [child3,child2,child1-2,child1-1]
      // node = [parent, child1-1] stack = [child3,child2,child1-2]
      for (let i = children.length - 1; i >= 0; i--) {
        stack.push(children[i])
      }
    }
  }
  return nodes
}

深度优先拷贝

目前只拷贝了Object, Array

// 如果是对象/数组,返回一个空的对象/数组,
// 都不是的话直接返回原对象
// 判断返回的对象和原有对象是否相同就可以知道是否需要继续深拷贝
// 处理其他的数据类型的话就在这里加判断
function getEmpty(o){
  if(Object.prototype.toString.call(o) === '[object Object]'){
    return {};
  }
  if(Object.prototype.toString.call(o) === '[object Array]'){
    return [];
  }
  return o;
}

function deepCopyBFS(origin){
  let queue = [];
  let map = new Map(); // 记录出现过的对象,用于处理环

  let target = getEmpty(origin);
  if(target !== origin){
    queue.push([origin, target]);
    map.set(origin, target);
  }

  while(queue.length){
    let [ori, tar] = queue.shift();
    for(let key in ori){
      // 处理环状
      if(map.get(ori[key])){
        tar[key] = map.get(ori[key]);
        continue;
      }

      tar[key] = getEmpty(ori[key]);
      if(tar[key] !== ori[key]){
        queue.push([ori[key], tar[key]]);
        map.set(ori[key], tar[key]);
      }
    }
  }

  return target;
}

function deepCopyDFS(origin){
  let stack = [];
  let map = new Map(); // 记录出现过的对象,用于处理环

  let target = getEmpty(origin);
  if(target !== origin){
    stack.push([origin, target]);
    map.set(origin, target);
  }

  while(stack.length){
    let [ori, tar] = stack.pop();
    for(let key in ori){
      // 处理环状
      if(map.get(ori[key])){
        tar[key] = map.get(ori[key]);
        continue;
      }

      tar[key] = getEmpty(ori[key]);
      if(tar[key] !== ori[key]){
        stack.push([ori[key], tar[key]]);
        map.set(ori[key], tar[key]);
      }
    }
  }

 return target;
}

评论

阅读下一篇

防抖节流的区别与实现
2019-07-19 11:31:28
0%