二叉树的遍历(深搜+广搜)
一、递归法
1. 前序遍历
代码框架:
void traversal(TreeNode* cur, vector<int>& vec) { if (cur == NULL) return; vec.push_back(cur->val); traversal(cur->left, vec); // 左 traversal(cur->right, vec); // 右 }
2. 中序遍历
代码框架:
void traversal(TreeNode* cur, vector<int>& vec) { if (cur == NULL) return; traversal(cur->left, vec); // 左 vec.push_back(cur->val); traversal(cur->right, vec); // 右 }
3. 后序遍历
代码框架:
void traversal(TreeNode* cur, vector<int>& vec) { if (cur == NULL) return; traversal(cur->left, vec); // 左 traversal(cur->right, vec); // 右 vec.push_back(cur->val); }
4. 举例:94. 二叉树的中序遍历 - 力扣(LeetCode) (leetcode-cn.com)
代码:
class Solution { void traverSal(TreeNode* cur,vector<int>& vec){ if (cur == NULL) return; traverSal(cur->left, vec); // 左 vec.push_back(cur->val); traverSal(cur->right, vec); // 右 } public: vector<int> inorderTraversal(TreeNode* root) { vector<int> result; traverSal(root,result); return result; } };
二、非递归法(迭代)
1. 前序遍历(深度优先搜索dfs)
(1)前序遍历是中左右,每次先处理的是中间节点,那么先将根节点放入栈中,然后将右孩子加入栈,再加入左孩子。
为什么要先加入 右孩子,再加入左孩子呢? 因为这样出栈的时候才是中左右的顺序。
(2)过程:自己试着画图
(3)代码框架
class Solution { public: vector<int> preorderTraversal(TreeNode* root) { stack<TreeNode*> st; vector<int> result; if (root == NULL) return result; st.push(root); while (!st.empty()) { TreeNode* node = st.top(); // 中 st.pop(); result.push_back(node->val); //输出 if (node->right) st.push(node->right); // 右(空节点不入栈) if (node->left) st.push(node->left); // 左(空节点不入栈) } return result; } };
2. 中序遍历
(1)中序遍历开始要一直遍历左孩子到底部,再处理节点,接着再遍历右孩子到底部,所以我们需要一个cur节点来表示当前遍历到哪个节点。
(2)代码框架
class Solution { public: vector<int> inorderTraversal(TreeNode* root) { vector<int> result; stack<TreeNode*> st; TreeNode* cur = root; while (cur != NULL || !st.empty()) { if (cur != NULL) { // 指针来访问节点,访问到最底层 st.push(cur); // 将访问的节点放进栈 cur = cur->left; // 左 } else { cur = st.top(); // 从栈里弹出的数据,就是要处理的数据(放进result数组里的数据) st.pop(); result.push_back(cur->val); // 中 cur = cur->right; // 右 } } return result; } };
3. 后序遍历
(1)因为前序遍历为:根-左-右,后序遍历为:左-右-根,因此我们普遍调整一下先序遍历的代码顺序,就变成根-右-左的遍历顺序,然后在反转result数组,输出的结果顺序就是左-右-根了。
(2)代码框架
class Solution { public: vector<int> postorderTraversal(TreeNode* root) { stack<TreeNode*> st; vector<int> result; if (root == NULL) return result; st.push(root); while (!st.empty()) { TreeNode* node = st.top(); st.pop(); result.push_back(node->val); if (node->left) st.push(node->left); // 相对于前序遍历,这更改一下入栈顺序 (空节点不入栈) if (node->right) st.push(node->right); // 空节点不入栈 } reverse(result.begin(), result.end()); // 将结果反转之后就是左右中的顺序了 return result; } };
三、层序遍历
dfs用的是栈,bfs则用队列,先进先出。
代码框架:
/* 层序遍历 */ //定义一个队列,结果数组 queue<TreeNode*> qu; vector<int> result; vector<int> queue(TreeNode* root){ if(root!=NULL) qu.push(root); while(!qu.empty()){ int size = qu.size(); //没while一次就是遍历每一层,这是每一层的大小 for(int i=0;i<size;i++){ //对每一层的每个节点进行处理,然后把每个节点的左右孩子入队 TreeNode* node = qu.front(); qu.pop(); result.push_back(node->val); if(node->left) qu.push(node->left); if(node->right) qu.push(node->right); } } return result; }