二叉樹使用遞歸實現前中後序遍歷是很是容易的,本文給出非遞歸實現前中後序遍歷的方法,核心的思想是使用一個棧,經過迭代來模擬遞歸的實現過程javascript
下面實現中root表明二叉樹根節點,每一個節點都具備left,right兩個指針,分別指向當前節點左右子樹,一個val屬性表明當前節點的值java
const preorderTraversal = function(root) {
const stack = [], res = []
root && stack.push(root)
// 使用一個棧stack,每次首先輸出棧頂元素,也就是當前二叉樹根節點,以後依次輸出二叉樹的左孩子和右孩子
while(stack.length > 0) {
let cur = stack.pop()
res.push(cur.val)
// 先入棧的元素後輸出,因此先入棧當前節點右孩子,再入棧左孩子
cur.right && stack.push(cur.right)
cur.left && stack.push(cur.left)
}
return res
};
複製代碼
const inorderTraversal = function(root) {
const res = [], stack = []
while(root || stack.length) {
// 中序遍歷,首先迭代左孩子,左孩子依次入棧
if(root.left) {
stack.push(root)
root = root.left
// 若是左孩子爲空了,輸出節點,去右孩子中迭代,
} else if(root.right) {
res.push(root.val)
root = root.right
// 若是左右孩子都爲空了,輸出當前節點,棧頂元素出棧,也就是回退到上一層,此時置空節點左孩子,防止while循環重複進入
} else if(!root.left && !root.right) {
res.push(root.val)
root = stack.pop()
root && (root.left = null)
}
}
return res
};
複製代碼
咱們在上一種方法裏,條件判斷root.left
,root.right
,其實咱們能夠只考慮當前節點node,這樣咱們只須要判斷node是否存在,簡化代碼node
const inorderTraversal = function(root) {
const res = [], stack = []
let node = root;
while (stack.length > 0 || node !== null) {
// 這裏用當前節點node是否存在,簡化代碼,
if (node) {
stack.push(node);
node = node.left
} else {
node = stack.pop();
res.push(node.val);
node = node.right;
}
}
return res;
};
複製代碼
// 1, 先依次遍歷左孩子, 在棧中依次記錄,當左孩子爲空時,遍歷到葉子節點 //跳回上一層節點, 爲防止while循環重複進入,將上一層左孩子置爲空
// 2, 接着遍歷右孩子, 在棧中依次記錄值,當右孩子爲空時, 遍歷到葉子節點
// 跳回上一層節點, 爲防止while循環重複進入,將上一層右孩子置爲空
const postorderTraversal = function(root) {
let res = [], stack = []
while (root || stack.length) {
if (root.left) {
stack.push(root)
root = root.left
} else if (root.right) {
stack.push(root)
root = root.right
} else {
res.push(root.val)
root = stack.pop()
if (root && root.left) root.left = null
else if (root && root.right) root.right = null
}
}
return res
};
複製代碼
再回頭看看前序遍歷的代碼,實際上後序遍歷和前序遍歷是一個逆序過程數組
// 結果數組中依次進入的是節點的左孩子,右孩子,節點自己,注意使用的是
// unshift,與前序遍歷push不一樣,每次數組頭部添加元素,實際上就是前序 遍歷的逆序過程
const postorderTraversal = function(root) {
const res = [], stack = []
while (root || stack.length) {
res.unshift(root.val)
root.left && stack.push(root.left)
root.right && stack.push(root.right)
root = stack.pop()
}
return res
};
複製代碼
// 和前序遍歷區別在於,結果數組res中入棧順序是當前節點,右孩子,左孩子,最後
// 使用js數組reverse方法反轉(逆序),使得輸出順序變爲左孩子,右孩子,當前節點,實現後序遍歷
const postorderTraversal = function(root) {
let stack = [], res = []
root && stack.push(root)
while(stack.length > 0) {
let cur = stack.pop()
res.push(cur.val)
cur.left && stack.push(cur.left)
cur.right && stack.push(cur.right)
}
return res.reverse()
};
複製代碼
本文詳細介紹了二叉樹前中後序遍歷的非遞歸實現,核心是藉助一個棧stack,使用迭代的方式模擬遞歸過程markdown