二叉樹知識參考:深入學習二叉樹(一) 二叉樹基礎
遞歸實現層次遍歷算法參考:【面經】用遞歸方法對二叉樹進行層次遍歷 && 二叉樹深度
上面第一篇基礎寫得不錯,不了解二叉樹的值得一看。
用遞歸來實現二叉樹的層次遍歷。lua實現
先上代碼:
function FindTree(tree, callback) local function Find(tree, level) if(tree == nil or level <= 0) then return false; end if (level == 1) then if callback then callback(tree.data); end return true; end local has_left = Find(tree.left, level - 1); local has_right = Find(tree.right, level - 1); return has_left or has_right; end local level = 1; while Find(tree, level, callback) do level = level + 1; end end
測試代碼:
a={}; a.data = "a" b, c = {}, {} b.data = "b" c.data = "c" a.left = b a.right = c d, e, f, g = {}, {}, {}, {} d.data = "d" e.data = "e" f.data = "f" g.data = "g" b.left = d b.right = e c.left = f c.right = g h, i, j = {}, {}, {} h.data = "h" i.data = "i" j.data = "j" d.left = h d.right = i e.left = j local list = {} FindTree(a, function(data) table.insert(list, data) end) print(table.concat(list, ", "))
結果:
基本思路 (下面的a是測試樹的根結點):
每步,都是一次從根到當前層級的自上而下的一次遍歷,從上到下找到第1層a, 從上到下找到第2層b,c,從上到下找到第3層d,e,f,g
詳細步驟:
1,FindTree(a, 1) : 如果此樹深度大於等於1,a結點的data通過回調傳回,函數返回true , while循環繼續;如果深度為0,a==null,直接返回false,while循環結束。
2,FindTree(a, 2):如果此樹深度大於等於2,傳回a的子結點(上圖b位置,或c位置,或bc位置)的data,返回true , while循環繼續;如果深度小於2,返回false,while循環結束。
這里就比較復雜了,需要對函數遞歸有一定的了解。執行到 has_left = FindTree(tree.left, level - 1); 時,現場被保留(后續代碼暫時不執行),程序再次進入到FindTree函數(即執行has_left = FindTree(b, 1)),當a有左子節點時,傳回a的左子節點的data,返回true,即 has_left =true; 否則 has_left = false; 然后執行到has_right = FindTree(tree.right, level - 1); 同理,如果有右子節點,傳回a的右子節點的data,返回true,即 has_right=true; 否則 has_right= false。如果a有左子節點或右子節點(或都有),整個函數返回true,while循環繼續;如果a沒有左結點和右結點,即深度小於2,has_left or has_right = false ,while循環結束。
3,FindTree(a, 3):如果此樹深度大於等於3,傳回a的深度為3的子結點(上圖d, e, f, g的各位置隨意組合)的data,返回true , while循環繼續;如果深度小於2,返回false,while循環結束。
同理,執行到 has_left = FindTree(tree.left, level - 1); 時,現場保留,直到has_left = FindTree(tree.left.left, level - 1 - 1); 即has_left = FindTree(d, 1),如果d結點不存在,返回false,has_left = false; 如果存在,打印d結點的data,返回true,has_left = true; e, f, g各個位置 的檢測同理。
4,…… , n - 1,
n,FindTree(a, n): 深度小於n (此樹深度為n-1),返回false,while循環結束。
用非遞歸來實現二叉樹的層次遍歷。lua實現
先上代碼:
function FindTree2(tree, callback) local nodeList = {tree} while #nodeList > 0 do local tempList = {} for i, v in ipairs(nodeList) do if callback then callback(v.data) end table.insert(tempList, v.left) table.insert(tempList, v.right) end nodeList = tempList; end end
測試代碼:如上
測試如果:如上
基本思路:從上到下,每一層從左到右依次遍歷。把每一層子節點存放在一個列表,直到這個列表為空,則遍歷完成。
這個方式比較直觀,直接看一下上面的圖和代碼,很容易理解。