數據結構與算法(樹) --javascript語言描述

重建二叉樹

輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。node

思路:二叉樹前序遍歷第一個點爲根節點,中序遍歷順序爲先左子樹而後根節點最後右子樹。因此先經過前序遍歷找出根節點,而後將中序遍歷分爲左右子樹兩組,最後對於每一個子樹依次遞歸調用。數組

function TreeNode(x) {
    this.val = x;
    this.left = null;
    this.right = null;
}
//pre爲前序遍歷序列數組 vin爲中序遍歷序列數組
function reConstructBinaryTree(pre, vin){
  if(pre.length == 0 || vin.length == 0) {
    return null;
  }
  let root = new TreeNode(pre[0]);
  //根節點在中序遍歷中的位置
  let index = vin.indexOf(pre[0]);
  let leftPre = pre.slice(1,index+1);//前序左子樹
  let rightPre = pre.slice(index+1);//前序右子屬
  let leftVin = vin.slice(0,index);//中序左子樹
  let rightVin = vin.slice(index+1);//中序右子樹
  //開始遞歸
  root.left = reConstructBinaryTree(leftPre,leftVin);
  root.right = reConstructBinaryTree(rightPre,rightVin);
  return root;
}

console.log(reConstructBinaryTree([1,2,4,7,3,5,6,8],[4,7,2,1,5,3,8,6]));

二叉樹的下一個節點

給定一個二叉樹和其中的一個結點,請找出中序遍歷順序的下一個結點而且返回。注意,樹中的結點不只包含左右子結點,同時包含指向父結點的指針。this

思路:根據中序遍歷的特色,要找到一個節點的下一個節點無非就是三種狀況:一、有右子樹,這時只須要把其右孩子做爲下一個遍歷的(並非要找的)節點,而後沿着該節點的左子樹(若是有的話)出發,直到遇到葉子節點,那麼該葉子節點就是其下一個要找的節點;二、沒有右子樹,則判斷該節點是不是其父節點的左孩子,若是是則其下一個要找的節點是其父節點;三、若是不是其父節點的左孩子,則把其父節點做爲下一個遍歷的節點,向上回溯,直到找到父節點沒有父節點而且父節點是父節點的父節點的左孩子爲止。綜合這三種狀況就能夠找到二叉樹中任意一個節點的下一個節點。指針

function TreeNode(x) {
    this.val = x;
    this.left = null;
    this.right = null;
    this.parent = null;
}
function getNext(node) {
  let curNode = null;
  //第1、判斷是否有右孩子
  if(node.right != null) {
    curNode = node.right;
    while(curNode.left !=null) {
      curNode = curNode.left;
    }
    return curNode;
  }
  //第2、判斷是不是其父節點的左孩子
  if(node.parent == null) {
    return null;
  }
  if(node.parent.left == node) {
    return node.parent;
  }
  //第3、向上找其父節點,直到父節點是其父節點的父節點的左孩子
  curNode = node.parent;
  while(curNode.parent != null) {
    if(curNode == curNode.parent.left) {
      return curNode.parent;
    }
    curNode = curNode.parent;
  }
  return null;
}

//構建二叉樹
let parentNode = createTree(
  ['a','b','d','e','h','i','c','f','g'],
  ['d','b','h','e','i','a','f','c','g']);

let i = parentNode.left.right.right;//i節點
let b = parentNode.left;//b節點
let f = parentNode.right.left;//f節點
console.log(getNext(i).val);//a
console.log(getNext(b).val);//h
console.log(getNext(f).val);//c

//根據前序遍歷和中序遍歷構建一顆二叉樹
function createTree(pre,vin){
  function TreeNode(x) {
      this.val = x;
      this.left = null;
      this.right = null;
      this.parent = null;
  }
  //pre爲前序遍歷序列數組 vin爲中序遍歷序列數組
  function reConstructBinaryTree(pre, vin,parent){
    if(pre.length == 0 || vin.length == 0) {
      return null;
    }
    let root = new TreeNode(pre[0]);
    //根節點在中序遍歷中的位置
    let index = vin.indexOf(pre[0]);
    let leftPre = pre.slice(1,index+1);//前序左子樹
    let rightPre = pre.slice(index+1);//前序右子屬
    let leftVin = vin.slice(0,index);//中序左子樹
    let rightVin = vin.slice(index+1);//中序右子樹
    //開始遞歸
    root.parent = parent;
    root.left = reConstructBinaryTree(leftPre,leftVin,root);
    root.right = reConstructBinaryTree(rightPre,rightVin,root);
    return root;
  }

  return reConstructBinaryTree(pre,vin,null);
}
相關文章
相關標籤/搜索