国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專(zhuān)欄INFORMATION COLUMN

推導(dǎo)二叉樹(shù)的遍歷結(jié)果

joy968 / 1844人閱讀

摘要:推導(dǎo)前序序列已知二叉樹(shù)的中序序列是,后序序列是,求前序序列。二叉樹(shù)的中序序列是按照左子樹(shù),根,右子樹(shù)的順序排列的,根將左子樹(shù)的序列和右子樹(shù)的序列分割在左右兩邊。

推導(dǎo)前序序列

已知二叉樹(shù)的中序序列是ABCDEFG,后序序列是BDCAFGE,求前序序列。

思路

二叉樹(shù)的后序序列是按照「左子樹(shù)」,「右子樹(shù)」,「根」的順序排列的,序列中最后一個(gè)元素代表該二叉樹(shù)的根節(jié)點(diǎn)。
二叉樹(shù)的前序序列是按照「根」,「左子樹(shù)」,「右子樹(shù)」的順序排列的,序列中第一個(gè)元素代表該二叉樹(shù)的根節(jié)點(diǎn)。故通過(guò)已知的后序序列可以發(fā)現(xiàn)根,作為前序序列的第一個(gè)元素。
二叉樹(shù)的中序序列是按照「左子樹(shù)」,「根」,「右子樹(shù)」的順序排列的,根將左子樹(shù)的序列和右子樹(shù)的序列分割在左右兩邊。通過(guò)后序序列發(fā)現(xiàn)根,找到其在中序序列的位置,從而在中序序列中發(fā)現(xiàn)左子樹(shù)和右子樹(shù)并獲得它們的長(zhǎng)度,最后在后序序列中找到對(duì)應(yīng)的左子樹(shù)和右子樹(shù)的后序序列。
這樣求某二叉樹(shù)的前序序列,變成了求該二叉樹(shù)左子樹(shù)的前序序列和該二叉樹(shù)右子樹(shù)的前序序列。

遞歸解法

一棵樹(shù),先找到其根,將其壓入棧中,再將其分割成左右子樹(shù),按左子樹(shù),右子樹(shù)的順序,找子樹(shù)的根,將其壓入棧中,直到子樹(shù)不可分割,得到整棵樹(shù)的前序序列。

/**
 * 返回二叉樹(shù)的前序序列
 * @param {array} inOrder 
 * @param {array} postOrder 
 * @returns {array} preOrder
 */
function findPreOrder (inOrder, postOrder) {
  let preOrder = []
  // 保存前序序列
  !function findRoot(inOrder, postOrder) {
    if (inOrder.length <= 1) { 
      // 若序列的長(zhǎng)度為0或1,停止遞歸調(diào)用
      inOrder[0] && preOrder.push(inOrder[0]) 
      // 若序列長(zhǎng)度為1,則它就是該樹(shù)的根節(jié)點(diǎn),根入棧
      // 在先序序列中,樹(shù)的根排列順序先于子樹(shù)的根
      return
    } else {
      const root = postOrder[postOrder.length - 1] 
      // 找到根節(jié)點(diǎn)
      preOrder.push(root) 
      // 根入棧
      const index = inOrder.indexOf(root) 
      // 找到根節(jié)點(diǎn)在中序序列中的位置
      const newInOrderLeft = inOrder.slice(0, index) 
      // 根據(jù)根的位置找出左子樹(shù)的中序序列
      const newInOrderRight = inOrder.slice(index + 1) 
      // 根據(jù)根的位置找出右子樹(shù)的中序序列
      const newPostOrderLeft = postOrder.slice(0, newInOrderLeft.length) 
      // 根據(jù)左子樹(shù)中序序列的長(zhǎng)度找出其后序序列
      const newPostOrderRight = postOrder.slice(newInOrderLeft.length, newInOrderRight.length + newInOrderLeft.length) 
      // 根據(jù)右子樹(shù)中序序列的長(zhǎng)度找出其后序序列
      findRoot(newInOrderLeft, newPostOrderLeft)
      // 找到左子樹(shù)的根
      findRoot(newInOrderRight, newPostOrderRight)
      // 找到右子樹(shù)的根
      // 在先序序列中,左子樹(shù)的根排列順序先于右子樹(shù)的根
    }
  }(inOrder, postOrder)
  return preOrder
  // 返回前序序列
}

let preOrder = findPreOrder(Array.from("ABCDEFG"), Array.from("BDCAFGE"))
console.log(preOrder)
// [ "E", "A", "C", "B", "D", "G", "F" ]
非遞歸解法

非遞歸解法和遞歸解法的思路相同,找到根,壓入棧,分割左右子樹(shù),找到它們的根,壓入棧。
不同之處在于用inOrderArr保存待分割的樹(shù)的中序序列,用postOrderArr保存待分割的樹(shù)的后序序列。

const findPreOrder = (inOrder, postOrder) => {
  let preOrder = [],
  // 保存前序序列
    inOrderArr = [inOrder],
    // 存儲(chǔ)待分割的樹(shù)的中序序列,初始狀態(tài)為傳入的樹(shù)的中序序列
    postOrderArr = [postOrder]
    // 存儲(chǔ)待分割的樹(shù)的后序序列,初始狀態(tài)為傳入的樹(shù)的后序序列
  while (preOrder.length < inOrder.length) {
    let inOrderEle = inOrderArr.shift(),
    // 取出子樹(shù)的中序序列
      postOrderEle = postOrderArr.shift()
      // 取出子樹(shù)的后序序列
    if (inOrderEle.length <= 1) {
    // 若取出的序列的長(zhǎng)度為0或1,就不再分割
      inOrderEle[0] && preOrder.push(inOrderEle[0])
      // 若取出的序列的長(zhǎng)度為1,則為根,入棧
    } else {
      let root = postOrderEle[postOrderEle.length - 1]
      // 找到根
      preOrder.push(root)
      // 根入棧
      // 開(kāi)始分割左右子樹(shù)
      const index = inOrderEle.indexOf(root)
      const newinOrderEle1 = inOrderEle.slice(0, index)
      const newinOrderEle2 = inOrderEle.slice(index + 1)
      inOrderArr = [newinOrderEle1, newinOrderEle2, ...inOrderArr] // 用分割后的左右子樹(shù)代替原先的樹(shù)
      const newpostOrderEle1 = postOrderEle.slice(0, newinOrderEle1.length)
      const newpostOrderEle2 = postOrderEle.slice(newinOrderEle1.length, newinOrderEle1.length + newinOrderEle2.length)
      postOrderArr = [newpostOrderEle1, newpostOrderEle2, ...postOrderArr] // 用分割后的左右子樹(shù)代替原先的樹(shù)
    }
  }
  return preOrder
  // 返回前序序列
}

let preOrder = findPreOrder(Array.from("ABCDEFG"), Array.from("BDCAFGE"))
console.log(preOrder)
// [ "E", "A", "C", "B", "D", "G", "F" ]
推導(dǎo)后序序列

已知二叉樹(shù)的前序序列是EACBDGF,中序序列是ABCDEFG,求后序序列。

思路

通過(guò)前序序列找到根,找到根在中序序列的位置,將樹(shù)分割成左右子樹(shù),按照先右子樹(shù)再左子樹(shù)的順序找到子樹(shù)的根,直至子樹(shù)不可分割。先找到的根排在后找到的根的后面。
和推導(dǎo)前序序列,相比思路大致相同,實(shí)現(xiàn)細(xì)節(jié)上,找樹(shù)的根的方式不同,分割子樹(shù)的方式不同,保存根的方式不同。

遞歸解法
const findPostOrder = (preOrder, inOrder) => {
  let postOrder = []
  // 保存后序序列
  !function findRoot(preOrder, inOrder) {
    if(inOrder.length <= 1){
    // 若序列的長(zhǎng)度為0或1,停止遞歸調(diào)用
      inOrder[0] && postOrder.unshift(inOrder[0])
      // 若序列長(zhǎng)度為1,則它就是該樹(shù)的根節(jié)點(diǎn),根入棧
      // 在后序序列中,樹(shù)的根排列順序后于子樹(shù)的根
      return
    }else{
      const root = preOrder[0]
      // 找到根節(jié)點(diǎn)
      postOrder.unshift(root)
      // 保存根
      const index = inOrder.indexOf(root)
      // 找到根節(jié)點(diǎn)在中序序列中的位置
      const newInOrderLeft = inOrder.slice(0, index)
      // 根據(jù)根的位置找出左子樹(shù)的中序序列
      const newInOrderRight = inOrder.slice(index + 1)
      // 根據(jù)根的位置找出右子樹(shù)的中序序列
      const newPreOrderLeft = preOrder.slice(1, newInOrderLeft.length + 1)
      // 根據(jù)左子樹(shù)中序序列的長(zhǎng)度找出其前序序列
      const newPreOrderRight = preOrder.slice(newInOrderLeft.length + 1)
      // 根據(jù)右子樹(shù)中序序列的長(zhǎng)度找出其前序序列
      findRoot(newPreOrderRight, newInOrderRight)
      // 找到右子樹(shù)的根
      findRoot(newPreOrderLeft, newInOrderLeft)
      // 找到左子樹(shù)的根
    }
  }(preOrder, inOrder)
  return postOrder
  // 返回后序序列
}

let postOrder = findPostOrder(Array.from("EACBDGF"), Array.from("ABCDEFG"))
console.log(postOrder)
// [ "B", "D", "C", "A", "F", "G", "E" ]
非遞歸解法

非遞歸解法和遞歸解法的思路相同,找到根并保存,分割左右子樹(shù),找到它們的根并保存。
不同之處在于用preOrderArr保存待分割的樹(shù)的前序序列,用inOrderArr保存待分割的樹(shù)的中序序列,且每次取最后一個(gè)元素開(kāi)始處理。

const findPostOrder = (preOrder, inOrder) => {
  let postOrder = [],
    preOrderArr = [preOrder],
    inOrderArr = [inOrder]
  while (postOrder.length < inOrder.length) {
    let inOrderEle = inOrderArr.pop(),
      preOrderEle = preOrderArr.pop()
    if (inOrderEle.length <= 1) {
      inOrderEle[0] && postOrder.unshift(inOrderEle[0])
    } else {
      let root = preOrderEle[0]
      postOrder.unshift(root)
      const index = inOrderEle.indexOf(root)
      const newinOrderEle1 = inOrderEle.slice(0, index)
      const newinOrderEle2 = inOrderEle.slice(index + 1)
      inOrderArr = [...inOrderArr, newinOrderEle1, newinOrderEle2]
      const newpreOrderEle1 = preOrderEle.slice(1, newinOrderEle1.length + 1)
      const newpreOrderEle2 = preOrderEle.slice(newinOrderEle1.length + 1)
      preOrderArr = [...preOrderArr, newpreOrderEle1, newpreOrderEle2]
    }
  }
  return postOrder
}

console.log(findPostOrder(Array.from("EACBDGF"), Array.from("ABCDEFG")))
// [ "B", "D", "C", "A", "F", "G", "E" ]
推導(dǎo)中序序列

那是不可能的!

已知前序序列ABC,后序序列CBA,求中序序列。

這是一道多解題。

推薦結(jié)合nodemon在node環(huán)境下學(xué)習(xí)算法。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/89204.html

相關(guān)文章

  • 數(shù)據(jù)結(jié)構(gòu):叉樹(shù)

    摘要:鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)由于二叉樹(shù)的每個(gè)結(jié)點(diǎn)最多有兩個(gè)孩子,所以為每個(gè)結(jié)點(diǎn)設(shè)計(jì)一個(gè)數(shù)據(jù)域和兩個(gè)指針域。最終能得到二叉樹(shù)的完整結(jié)構(gòu)。這篇文章主要介紹樹(shù)結(jié)構(gòu)中的一種特殊存在——二叉樹(shù)。主要內(nèi)容有: 二叉樹(shù)的概念 二叉樹(shù)的基本結(jié)構(gòu) 二叉樹(shù)的操作 概念 二叉樹(shù): 每個(gè)結(jié)點(diǎn)最多有兩個(gè)子結(jié)點(diǎn),兩個(gè)子結(jié)點(diǎn)是有次序的,且子結(jié)點(diǎn)次序不能顛倒。兩個(gè)子結(jié)點(diǎn)一般稱(chēng)之為左結(jié)點(diǎn)及右結(jié)點(diǎn)。 層次: 在樹(shù)中,節(jié)點(diǎn)的層次從...

    Ashin 評(píng)論0 收藏0
  • 【數(shù)據(jù)結(jié)構(gòu)初階】第八篇——二叉樹(shù)的鏈?zhǔn)浇Y(jié)構(gòu)(二叉樹(shù)的前、中和后序遍歷+層序遍歷+鏈?zhǔn)浇Y(jié)構(gòu)的實(shí)現(xiàn)+相關(guān)

    摘要:代碼實(shí)現(xiàn)如下二叉樹(shù)的創(chuàng)建與銷(xiāo)毀二叉樹(shù)的創(chuàng)建問(wèn)題通過(guò)前序遍歷的數(shù)組給定一串字符串,代表的是空樹(shù),其他的都是節(jié)點(diǎn)。 ??本篇博客我要來(lái)和大家一起聊一聊數(shù)據(jù)結(jié)構(gòu)中的二...

    BigNerdCoding 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<