1

树的遍历 Tree Traversals

   let root = {
       val: 1,
       left:{
         val: 2,
         left: {
            val: 3,
            left: {
                val: 5
            }
         },
         right: {
            val: 4,
            right: {
                val: 6
            } 
         }
       },
       right:{
           val: 7,
           left: {
               val: 8
           },
           right:{
               val: 9,
               right: {
                   val: 10
               }
           }
       } 
    };

0. 二叉树的序列化与反序列化

序列化二叉树:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串。需要注意的是,序列化二叉树的过程中,如果遇到空节点,需要以某种符号(这里用#)表示。
反序列化二叉树:根据某种遍历顺序得到的序列化字符串,重构二叉树。具体思路是按前序遍历“根左右”的顺序,根节点位于其左右子节点的前面,即非空(#)的第一个节点是某子树的根节点,左右子节点在该根节点后,以空节点#为分隔符。

1. 序列化二叉树

    function serializeTree(root, nodes = []) {
        if (!root) {
            nodes.push("#");
        } else {
            nodes.push(root.val);
            serializeTree(root.left, nodes);
            serializeTree(root.right, nodes);
        }
        return nodes.join(",");
    }
    serializeTree(root); //"1,2,3,5,#,#,#,4,#,6,#,#,7,8,#,#,9,#,10,#,#"

2. 反序列化二叉树

    function deserializeTree(nodeStr){
        if (!nodeStr) {
            return null;
        }
        return deserialize(nodeStr.split(","));
    }
    function deserialize(nodes) {
        let root = null;
        const current = nodes.shift();
        if (current !== "#") {
            root = { val: current };
            root.left = deserialize(nodes);
            root.right = deserialize(nodes);
        }
        return root;
    }
    deserializeTree("1,2,3,5,#,#,#,4,#,6,#,#,7,8,#,#,9,#,10,#,#"); // root

1.广度优先遍历 Breadth First Traversal

1. 层级遍历 Level Order

Algorithm Postorder(tree)
   1. Visit the root. 先访问根节点
   2. Traverse the deeper level, visit child root. call levelorder(node, depth)
   3. Continue traverse the deeper level, visit child root. call levelorder(node, depth)
   ...
 var levelOrder = function(root) {
    var orders= [];
    levelorder(root, 0)
    return orders;
    
    function levelorder(node, depth) {
        if (!node) {
            return;
        }
        orders[depth] = orders[depth] || [];
        orders[depth].push(node.val);
        levelorder(node.left, depth + 1);
        levelorder(node.right, depth + 1);
    }    
};

console.warn("levelOrder", levelOrder(root));
Output: "levelorder": [[1], [2, 7], [3, 4, 8, 9], [5, 6, 10]]

2. 深度优先遍历 Depth First Traversals

1. 后序遍历 Postorder (Left, Right, Root)

Algorithm Postorder(tree)
   1. Traverse the left subtree, i.e., call Postorder(left-subtree) 首先遍历左子树
   2. Traverse the right subtree, i.e., call Postorder(right-subtree) 然后遍历右子树
   3. Visit the root. 最后访问根节点
  var postorderTraversal = function(root) {
      var orders = [];
      postorder(root);
      return orders;
    
      function postorder(node) {
         if (node ) {
                if (isValidValue(node.left)) {
                    postorder(node.left);
                }
        
                if (isValidValue(node.right)) {
                    postorder(node.right);
                }
                
                if (isValidValue(node.val)) {
                    orders.push(node.val);
                } 
            }
        }
        
        function isValidValue(node) {
            return node !== null && node !== undefined && node !== "";
        }
    };
    
    console.warn("postorder", postorderTraversal(root));
Output: "postorder": [5, 3, 6, 4, 2, 8, 10, 9, 7, 1]

2. 中序遍历 Inorder (Left, Root, Right)

Algorithm Inorder(tree)
   1. Traverse the left subtree, i.e., call Inorder(left-subtree) 首先遍历左子树
   2. Visit the root. 然后访问根节点
   3. Traverse the right subtree, i.e., call Inorder(right-subtree) 最后遍历右子树
    var inorderTraversal = function(root) {
        var orders = [];
        inorder(root);
        return orders;
    
        function inorder(node) {
            if (node ) {
                if (isValidValue(node.left)) {
                    inorder(node.left);
                }
                
                if (isValidValue(node.val)) {
                    orders.push(node.val);
                }
              
                if (isValidValue(node.right)) {
                    inorder(node.right);
                }
            }
        }
        
        function isValidValue(node) {
            return node !== null && node !== undefined && node !== "";
        }
    };
    
    console.warn("inorder", inorderTraversal(root));
    
Output: "inorder": [5, 3, 2, 4, 6, 1, 8, 7, 9, 10]

3. 前序遍历 Preorder (Root, Left, Right)

Algorithm Preorder(tree)
   1. Visit the root. 首先访问根节点
   2. Traverse the left subtree, i.e., call Preorder(left-subtree) 然后遍历左子树
   3. Traverse the right subtree, i.e., call Preorder(right-subtree) 最后遍历右子树
``
var preorderTraversal = function(root) {
    var orders = [];
    preorder(root);
    return orders;

    function preorder(node) {
        if (node ) {
            if (isValidValue(node.val)) {
                orders.push(node.val);
            }
     
            if (isValidValue(node.left)) {
                preorder(node.left);
            }
    
            if (isValidValue(node.right)) {
                preorder(node.right);
            }
        }
    }
    
    function isValidValue(node) {
        return node !== null && node !== undefined && node !== "";
    }
};

console.warn("preorder", preorderTraversal(root));

>  Output: "preorder" [1, 2, 3, 5, 4, 6, 7, 8, 9, 10]


肾导
1.7k 声望105 粉丝

渐渐成熟的前端工程师。