[leetcode] 二叉树的前序,中序,后续,层次遍历
前序遍历
[144] Binary Tree Preorder Traversal
递归遍历
使用递归,先保存父节点的值,再对左子树进行遍历(递归),最后对右子树进行遍历(递归)
vector<int> preorderTraversal(TreeNode* root) { vector<int> re; preTraversal(root, re); return re; } void preTraversal(TreeNode* root, vector<int>& re) { if (!root) { return; } re.push_back(root->val); preTraversal(root->left, re); preTraversal(root->right, re); }
非递归遍历
方法一: 使用一个辅助栈(利用栈的后进先出的特性),先一直找左子树直到左子树为null(此过程中将遍历到的节点的值保存并且将这些节点压入栈中)。再弹出栈顶元素,对其右子树再做以上操作。直到栈为空。
vector<int> preorderTraversal(TreeNode* root) { vector<int> vec; stack<TreeNode*> st; while (root or !st.empty()) { while (root) { vec.push_back(root->val); st.push(root); root = root->left; } if (!st.empty()) { auto temp = st.top(); st.pop(); root = temp->right; } } return vec; }
方法二:
使用一个辅助栈来完成(利用栈的后进先出的特性)。先将父节点的值保存,然后将右子树压入栈中,再将左子树压入栈中(注意顺序,要保证出栈的时候左子树在右子树先)。再对栈顶元素进行上述操作。直到栈为空。
vector<int> postorderTraversal(TreeNode* root) { vector<int> re; if (!root) { return re; } stack<TreeNode*> st; st.push(root); while (!st.empty()) { auto tmp = st.top(); re.push_back(tmp->val); st.pop(); if (tmp->right) { st.push(tmp->right); } if (tmp->left) { st.push(tmp->left); } } return re; }
中序遍历
[94] Binary Tree Inorder Traversal
递归遍历
使用递归,再对左子树进行遍历(递归),先保存父节点的值,最后对右子树进行遍历(递归)
vector<int> inorderTraversal(TreeNode* root) { vector<int> re; inTraversal(root, re); return re; } void inTraversal(TreeNode* root, vector<int>& re) { if (!root) { return; } inTraversal(root->left, re); re.push_back(root->val); inTraversal(root->right, re); }
非递归遍历
后前序遍历思路一致,只是保存值的地方改变了。在节点出栈的时候再保存值,这样可以实现先保存左子树的值再保存父节点的值。
vector<int> inorderTraversal(TreeNode* root) { vector<int> vec; stack<TreeNode*> st; while (root or !st.empty()) { while (root) { st.push(root); root = root->left; } if (!st.empty()) { auto temp = st.top(); vec.push_back(temp->val); st.pop(); root = temp->right; } } return vec; }
后序遍历
[145] Binary Tree Postorder Traversal
递归遍历
使用递归,再对左子树进行遍历(递归),再对右子树进行遍历(递归),最后先保存父节点的值
vector<int> postorderTraversal(TreeNode* root) { vector<int> re; traversal(root, re); return re; } void traversal(TreeNode* root, vector<int>& re) { if (!root) { return; } traversal(root->left, re); traversal(root->right, re); re.push_back(root->val); }
非递归遍历
前序遍历:根-左-右
后续遍历:左-右-根
可以看到,在前序遍历的时候先遍历右子树再遍历左子树那么顺序就变成了根-右-左,再翻转就变成了后续遍历 左-右-根。根据此思路我们可以先对前序遍历的非递归遍历方法二进行一点点改造,再把结果翻转,就得到了后续遍历的非递归遍历的结果
vector<int> postorderTraversal(TreeNode* root) { vector<int> re; if (!root) { return re; } stack<TreeNode*> st; st.push(root); while (!st.empty()) { auto tmp = st.top(); re.push_back(tmp->val); st.pop(); if (tmp->left) { st.push(tmp->left); } if (tmp->right) { st.push(tmp->right); } } reverse(re.begin(), re.end()); return re; }
层次遍历
[102] Binary Tree Level Order Traversal
使用一个辅助队列(利用队列的先进先出特性)。将根节点压入队列中,获取当前队列大小,对当前队列中的所有节点进行遍历,保存其值,若其左右子树非空,则将其入队。直到队列为空为止。
vector<vector<int>> levelOrder(TreeNode* root) { queue<TreeNode*> qu; vector<vector<int>> re; qu.push(root); while (!qu.empty() and root) { vector<int> tmp; int size = qu.size(); for (int i = 0; i < size; ++i) { auto ele = qu.front(); qu.pop(); tmp.push_back(ele->val); if (ele->left) { qu.push(ele->left); } if (ele->right) { qu.push(ele->right); } } re.push_back(tmp); } return re; }