(3)算法 二叉树

107 阅读2分钟

探索部分 二叉树

(1)二叉树的遍历

递归方法

function TreeNode (val) {
  this.val = val;
  this.left = this.right = null;
}
//定义一个二叉树 [1,null,2,3]
var root = new TreeNode(1);
var rootr = new TreeNode(2);
var rootrl = new TreeNode(3);
root.left = null;
root.right = rootr;
rootr.left = rootrl;
rootr.right = null;
rootrl.left = null;
rootrl.right = null;
//递归版本
// 前序遍历
var preorderTraversal = function (root) {
  if (root) {
    console.log(root.val)
    preorderTraversal(root.left);
    preorderTraversal(root.right);
  }
};
// 中序遍历
var inorderTraversal = function (root) {
  if (root) {
    inorderTraversal(root.left)
    console.log(root.val);
    inorderTraversal(root.right)
  }
};
// 后续遍历
var postorderTraversal = function (root) {
  if (root) {
    postorderTraversal(root.left)
    postorderTraversal(root.right)
    console.log(root.val)
  }
};

preorderTraversal(root) // 1 2 3
inorderTraversal(root) //1 3 2 
postorderTraversal(root) //3 2 1

非递归方法

/**
 * @param {TreeNode} root
 * @return {number[]}
 */
function TreeNode (val) {
  this.val = val;
  this.left = this.right = null;
}
//定义一个二叉树 [1,null,2,3]
var root = new TreeNode(1);
var rootr = new TreeNode(2);
var rootrl = new TreeNode(3);
root.left = null;
root.right = rootr;
rootr.left = rootrl;
rootr.right = null;
rootrl.left = null;
rootrl.right = null;
//非递归版本
// 前序遍历 
var preorderTraversal = function (root) {
  if (root === null) return []
  var stack = [];
  stack.push(root)
  var res = [];
  while (stack.length != 0) {
    var node = stack.pop();  //先把根出栈
    if (node != null) {
      res.push(node.val)    
      stack.push(node.right)   //先右后左 这样左边的先出来
      stack.push(node.left)
    }
  }
  return res

};
// 中序遍历
var inorderTraversal = function (root) {
  if (root === null) return []
  var stack = [];     
  var res = [];
  var node = root;
  while (stack.length != 0 || node) { 
    if (node != null) {
      stack.push(node);
      node = node.left;  //向左找到第一个没有左孩子的节点
    }
    else {
      node = stack.pop()  //出栈 然后去找他的右孩子
      res.push(node.val)
      node = node.right;
    }
  }
  return res
};
// 后序遍历
var postorderTraversal = function (root) {
  var stack = [root];
  var res = [];
  var node = root;
  while (stack.length != 0) {
    var tmp = stack[stack.length - 1]; //栈顶元素
    if (tmp.left != null && node != tmp.left && node != tmp.right) { //判断栈顶元素有左孩子,且左右孩子都没有在上次弹出
      stack.push(tmp.left);       //左孩子入栈
    }
    else if (tmp.right != null && node != tmp.right) { //没有左孩子但是右孩子,且有孩子没有在上一次弹出,就入栈
      stack.push(tmp.right);
    }
    else {//左右孩子都没有,或者都遍历过,就出栈
      var r = stack.pop();
      res.push(r.val)
      node = tmp;  //当有元素出栈时,node是刚弹出的元素
    } 
  }
  return res;
};

var preorder = preorderTraversal(root)
console.log(preorder); // 1 2 3
var inorder = inorderTraversal(root)
console.log(inorder)  //1 3 2 
var postorder = postorderTraversal(root) //3 2 1
console.log(postorder)

层次遍历

var leveOrderTranversal = function (root) {
  var queue = [];
  var res = [];
  queue.push(root)
  while (queue.length != 0) {
    var node = queue.shift();
    res.push(node.val)  
    if (node.left != null) queue.push(node.left);    //每次出队之后让左右孩子入队
    if (node.right != null) queue.push(node.right)
  }
  return res;
}

序列化和反序列化