關於二叉樹的遍歷在面試時是企業常常容易考到的題目,這裏作一下總結。面試
二叉樹有前序遍歷,中序遍歷和後序遍歷三種。關於這三種遍歷,網上資料有不少,在此就不作詳細介紹了。主要須要記住順序:函數
遞歸時僅須要按照上述順序就能夠了。post
void preOrder(TreeNode* root) { if (!root) { return; } cout << root->val; preOrder(root->left); preOrder(root->right); }
void inOrder(TreeNode* root) { if (!root) { return; } inOrder(root->left); cout << root->val; inOrder(root->right); }
void postOrder(TreeNode* root) { if (!root) { return; } postOrder(root->left); postOrder(root->right); cout << root->val; }
可見遞歸版本實現起來很是簡單,面試的時候,每每面試官會強制你寫出非遞歸的版本,網上關於非遞歸版本的介紹也有不少,這裏我分享一個本身認爲是比較好記的版本。spa
顯然,咱們須要用一個stack來模擬遞歸時的函數調用。對於三種遍歷,咱們都使用push當前節點->push左子樹->pop左子樹->push右子樹->pop右子樹的方式。可是cout時機會有所不一樣。指針
對於前序遍從來說,每次訪問到一個節點就cout;code
對於中序遍從來說,每次將右子節點進棧時,把當前節點cout;blog
對於後序遍從來說,每次pop的時候cout。遞歸
另外咱們還須要一個last_pop指針來存放上一個pop出去的節點。it
若是當前節點的左右節點都不是上一個pop的節點,那麼咱們將左子節點入棧;ast
若是當前節點的左節點是上一個pop的節點,但右節點不是,那麼就把右子節點入棧;
不然的話,就須要讓當前節點出棧。
大體思路就是這樣,俗話說Talk is cheap, let's coding. 直接上代碼,注意三種遍歷的代碼整體結構都是徹底同樣的,只是cout的時機有所不一樣。
void preorder_traversal_iteratively(TreeNode* root) { if (root == 0) return; stack<TreeNode*> s; s.push(root); cout << root->val << ' '; // visit root TreeNode* last_pop = root; while (!s.empty()) { TreeNode* top = s.top(); if (top->left != 0 && top->left != last_pop && top->right != last_pop) // push_left { s.push(top->left); cout << top->left->val << ' '; // visit top->left } else if (top->right != 0 && top->right != last_pop && (top->left == 0 || top->left == last_pop)) // push_right { s.push(top->right); cout << top->right->val << ' '; // visit top->right } else // pop { s.pop(); last_pop = top; } } }
void inorder_traversal_iteratively(TreeNode* root) { if (root == 0) return; stack<TreeNode*> s; s.push(root); TreeNode* last_pop = root; while (!s.empty()) { TreeNode* top = s.top(); if (top->left != 0 && top->left != last_pop && top->right != last_pop) // push_left { s.push(top->left); } else if (top->right != 0 && top->right != last_pop && (top->left == 0 || top->left == last_pop)) // push_right { s.push(top->right); cout << top->val << ' '; // visit top } else // pop { s.pop(); last_pop = top; if (top->right == 0) cout << top->val << ' '; // visit top } } }
void postorder_traversal_iteratively(TreeNode* root) { if (root == 0) return; stack<TreeNode*> s; s.push(root); TreeNode* last_pop = root; while (!s.empty()) { TreeNode* top = s.top(); if (top->left != 0 && top->left != last_pop && top->right != last_pop) // push_left { s.push(top->left); } else if (top->right != 0 && top->right != last_pop && (top->left == 0 || top->left == last_pop)) // push_right { s.push(top->right); } else // pop { s.pop(); last_pop = top; cout << top->val << ' '; // visit top } } }