JS中的二叉樹遍歷詳解
來源:易賢網(wǎng) 閱讀:1030 次 日期:2016-07-19 15:08:28
溫馨提示:易賢網(wǎng)小編為您整理了“JS中的二叉樹遍歷詳解”,方便廣大網(wǎng)友查閱!

這篇文章主要為大家詳細(xì)介紹了JS中的二叉樹遍歷,何為二叉樹,什么是二叉樹的遍歷,感興趣的小伙伴們可以參考一下

二叉樹是由根節(jié)點(diǎn),左子樹,右子樹組成,左子樹和友子樹分別是一個(gè)二叉樹。

這篇文章主要在JS中實(shí)現(xiàn)二叉樹的遍歷。

一個(gè)二叉樹的例子

var tree = {

 value: 1,

 left: {

  value: 2,

  left: {

   value: 4

  }

 },

 right: {

  value: 3,

  left: {

   value: 5,

   left: {

    value: 7

   },

   right: {

    value: 8

   }

  },

  right: {

   value: 6

  }

 }

}

廣度優(yōu)先遍歷

廣度優(yōu)先遍歷是從二叉樹的第一層(根結(jié)點(diǎn))開始,自上至下逐層遍歷;在同一層中,按照從左到右的順序?qū)Y(jié)點(diǎn)逐一訪問。

實(shí)現(xiàn):

<!--more-->

使用數(shù)組模擬隊(duì)列。首先將根節(jié)點(diǎn)歸入隊(duì)列。當(dāng)隊(duì)列不為空的時(shí)候,執(zhí)行循環(huán):取出隊(duì)列的一個(gè)節(jié)點(diǎn),如果該結(jié)點(diǎn)的左子樹為非空,則將該結(jié)點(diǎn)的左子樹入隊(duì)列;如果該結(jié)點(diǎn)的右子樹為非空,則將該結(jié)點(diǎn)的右子樹入隊(duì)列。

(描述有點(diǎn)不清楚,直接看代碼吧。)

var levelOrderTraversal = function(node) { 

 if(!node) {  

  throw new Error('Empty Tree')

 } 

 var que = []

 que.push(node) 

 while(que.length !== 0) {

  node = que.shift()  

  console.log(node.value)  

  if(node.left) que.push(node.left)  

  if(node.right) que.push(node.right)

 }

}

遞歸遍歷

覺得用這幾個(gè)字母表示遞歸遍歷的三種方法不錯(cuò):

D:訪問根結(jié)點(diǎn),L:遍歷根結(jié)點(diǎn)的左子樹,R:遍歷根結(jié)點(diǎn)的右子樹。

先序遍歷:DLR

中序遍歷:LDR

后序遍歷:LRD

順著字母表示的意思念下來就是遍歷的順序了 ^ ^

這3種遍歷都屬于遞歸遍歷,或者說深度優(yōu)先遍歷(Depth-First Search,DFS),因?yàn)樗?/P>

是優(yōu)先往深處訪問。

先序遍歷的遞歸算法:

var preOrder = function (node) { 

 if (node) {  

  console.log(node.value);

  preOrder(node.left);

  preOrder(node.right);

 }

}

中序遍歷的遞歸算法:

var inOrder = function (node) { 

 if (node) {

  inOrder(node.left);  

  console.log(node.value);

  inOrder(node.right);

 }

}

后序遍歷的遞歸算法:

var postOrder = function (node) { 

 if (node) {

  postOrder(node.left);

  postOrder(node.right);  

  console.log(node.value);

 }

}

非遞歸深度優(yōu)先遍歷

其實(shí)對(duì)于這些概念誰是屬于誰的我也搞不太清楚。有的書里將二叉樹的遍歷只講了上面三種遞歸遍歷。有的分廣度優(yōu)先遍歷和深度優(yōu)先遍歷兩種,把遞歸遍歷都分入深度遍歷當(dāng)中;有的分遞歸遍歷和非遞歸遍歷兩種,非遞歸遍歷里包括廣度優(yōu)先遍歷和下面這種遍歷。個(gè)人覺得怎么分其實(shí)并不重要,掌握方法和用途就好 :)

剛剛在廣度優(yōu)先遍歷中使用的是隊(duì)列,相應(yīng)的,在這種不遞歸的深度優(yōu)先遍歷中我們使用棧。在JS中還是使用一個(gè)數(shù)組來模擬它。

這里只說先序的:

額,我嘗試了描述這個(gè)算法,然而并描述不清楚,按照代碼走一邊你就懂了。

var preOrderUnRecur = function(node) { 

 if(!node) {  

  throw new Error('Empty Tree')

 } 

 var stack = []

 stack.push(node) 

 while(stack.length !== 0) {

  node = stack.pop()  

  console.log(node.value)  

  if(node.right) stack.push(node.right)  

  if(node.left) stack.push(node.left)

 }

}

看了這一篇,找到了非遞歸后序的算法,所以在這里把非遞歸的遍歷方法補(bǔ)充完整。

非遞歸中序

先把數(shù)的左節(jié)點(diǎn)推入棧,然后取出,再推右節(jié)點(diǎn)。

var inOrderUnRecur = function(node) { 

 if(!node) {  

  throw new Error('Empty Tree')

 } 

 var stack = [] 

 while(stack.length !== 0 || node) {  

  if(node) {

   stack.push(node)

   node = node.left

  } else {

   node = stack.pop()   

   console.log(node.value)

   node = node.right

  }

 }

}

非遞歸后序(使用一個(gè)棧)

這里使用了一個(gè)臨時(shí)變量記錄上次入棧/出棧的節(jié)點(diǎn)。思路是先把根節(jié)點(diǎn)和左樹推入棧,然后取出左樹,再推入右樹,取出,最后取跟節(jié)點(diǎn)。

var posOrderUnRecur = function(node) { 

 if(!node) {  

  throw new Error('Empty Tree')

 } 

 var stack = []

 stack.push(node) 

 var tmp = null

 while(stack.length !== 0) {

  tmp = stack[stack.length - 1]  

  if(tmp.left && node !== tmp.left && node !== tmp.right) {

   stack.push(tmp.left)

  } else if(tmp.right && node !== tmp.right) {

   stack.push(tmp.right)

  } else {   

   console.log(stack.pop().value)

   node = tmp

  }

 }

}

非遞歸后序(使用兩個(gè)棧)

這個(gè)算法的思路和上面那個(gè)差不多,s1有點(diǎn)像一個(gè)臨時(shí)變量。

var posOrderUnRecur = function(node) { 

 if(node) {  

  var s1 = []  

  var s2 = []

  s1.push(node)  

  while(s1.length !== 0) {

   node = s1.pop()

   s2.push(node)   

   if(node.left) {

    s1.push(node.left)

   }   

   if(node.right) {

    s1.push(node.right)

   }

  }  

  while(s2.length !== 0) {   

   console.log(s2.pop().value);

  }

 }

}

Morris遍歷

這個(gè)方法即不用遞歸也不用棧實(shí)現(xiàn)三種深度遍歷,空間復(fù)雜度為O(1)(這個(gè)概念我也不是特別清楚org)

(這三種算法我先放著,有空再研究)

Morris先序:

var morrisPre = function(head) { 

 if(!head) {  

  return

 } 

 var cur1 = head,

   cur2 = null

 while(cur1) {

  cur2 = cur1.left  

  if(cur2) {   

   while(cur2.right && cur2.right != cur1) {

    cur2 = cur2.right

   }   

   if(!cur2.right) {

    cur2.right = cur1    

    console.log(cur1.value)

    cur1 = cur1.left    

    continue

   } else {

    cur2.right = null

   }

  } else {   

    console.log(cur1.value)

  }

  cur1 = cur1.right

 }

}

Morris中序:

var morrisIn = function(head) { 

 if(!head) {  

  return

 } 

 var cur1 = head,

   cur2 = null

 while(cur1) {

  cur2 = cur1.left  

  if(cur2) {   

   while(cur2.right && cur2.right !== cur1) {

    cur2 = cur2.right

   }   

   if(!cur2.right) {

    cur2.right = cur1

    cur1 = cur1.left    

    continue

   } else {

    cur2.right = null

   }

  }  

  console.log(cur1.value)

  cur1 = cur1.right

 }

}

Morris后序:

var morrisPost = function(head) { 

 if(!head) {  

  return

 } 

 var cur1 = head,

   cur2 = null

 while(cur1) {

  cur2 = cur1.left  

  if(cur2) {   

   while(cur2.right && cur2.right !== cur1) {

    cur2 = cur2.right

   }   

   if(!cur2.right) {

    cur2.right = cur1

    cur1 = cur1.left    

    continue

   } else {

    cur2.right = null

    printEdge(cur1.left)

   }

  }

  cur1 = cur1.right

 }

 printEdge(head)

}

var printEdge = function(head) { 

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助。

更多信息請(qǐng)查看網(wǎng)絡(luò)編程
易賢網(wǎng)手機(jī)網(wǎng)站地址:JS中的二叉樹遍歷詳解
由于各方面情況的不斷調(diào)整與變化,易賢網(wǎng)提供的所有考試信息和咨詢回復(fù)僅供參考,敬請(qǐng)考生以權(quán)威部門公布的正式信息和咨詢?yōu)闇?zhǔn)!

2025國(guó)考·省考課程試聽報(bào)名

  • 報(bào)班類型
  • 姓名
  • 手機(jī)號(hào)
  • 驗(yàn)證碼
關(guān)于我們 | 聯(lián)系我們 | 人才招聘 | 網(wǎng)站聲明 | 網(wǎng)站幫助 | 非正式的簡(jiǎn)要咨詢 | 簡(jiǎn)要咨詢須知 | 新媒體/短視頻平臺(tái) | 手機(jī)站點(diǎn) | 投訴建議
工業(yè)和信息化部備案號(hào):滇ICP備2023014141號(hào)-1 云南省教育廳備案號(hào):云教ICP備0901021 滇公網(wǎng)安備53010202001879號(hào) 人力資源服務(wù)許可證:(云)人服證字(2023)第0102001523號(hào)
云南網(wǎng)警備案專用圖標(biāo)
聯(lián)系電話:0871-65099533/13759567129 獲取招聘考試信息及咨詢關(guān)注公眾號(hào):hfpxwx
咨詢QQ:1093837350(9:00—18:00)版權(quán)所有:易賢網(wǎng)
云南網(wǎng)警報(bào)警專用圖標(biāo)