二叉树遍历递归法
前序遍历力扣题目链接、中序遍历力扣题目链接、后序遍历力扣题目链接
思路:
- 递归法很简单,三部曲:
1. 确定函数参数和返回值:参数为二叉树节点和结果集,返回值为空
2. 确定递归退出条件:当节点为空时退出
3. 确定单层逻辑:前序遍历是中左右的循序,中序遍历是左中右,后序遍历是左右中,所以前序遍历在单层递归的逻辑,是要先取中节点的数值,然后分别递归左孩子和右孩子,剩下两个对应写就行。
代码实现:
- 前序遍历
void Traversal(TreeNode* root, vector<int>& vec) {
if (root == nullptr) {
return;
}
vec.push_back(root->val);
Traversal(root->left, vec);
Traversal(root->right, vec);
return;
}
vector<int> preorderTraversal(TreeNode* root) {
vector<int> results;
Traversal(root, results);
return results;
}
- 中序遍历
void traversal(TreeNode* cur, vector<int>& vec) {
if (root == nullptr) {
return;
}
traversal(cur->left, vec); // 左
vec.push_back(cur->val); // 中
traversal(cur->right, vec); // 右
}
vector<int> inorderTraversal(TreeNode* root) {
vector<int> results;
Traversal(root, results);
return results;
}
- 后序遍历
void Traversal(TreeNode* root, vector<int>& vec) {
if (root == nullptr) {
return;
}
Traversal(root->left, vec);
Traversal(root->right, vec);
vec.push_back(root->val);
return;
}
vector<int> postorderTraversal(TreeNode* root) {
vector<int> results;
Traversal(root, results);
return results;
}
二叉树遍历迭代法
前序遍历
思路
- 借助栈来模拟中左右的遍历过程,但是注意要先将右孩子节点存入栈中。
代码实现
vector<int> preorderTraversal(TreeNode* root) {
if (root == nullptr) {
return {};
}
stack<TreeNode*> stk;
vector<int> results;
stk.push(root);
while(!stk.empty()) {
TreeNode* cur = stk.top();
stk.pop();
results.push_back(cur->val);
if(cur->right) stk.push(cur->right);
if(cur->left) stk.push(cur->left);
}
return results;
}
中序遍历
思路
- 同样借助栈来模拟左中右的遍历过程,但是和前序遍历略有不同,我们需要先找到左子树最大深度的左节点才能处理,所以处理(将元素放入结果集中)和访问(遍历二叉树)不是同时进行的,而前序遍历是中左右,那么处理和访问是同时进行的,因此需要借助指针来去访问,借助栈来处理。
代码实现
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;
}
后序遍历
思路
- 方法一:前序遍历是右左的压栈顺序,得到的结果是中左右,而我们将前序的压栈顺序换成左右,得到的结果是中右左,然后将结果集反转即可。
- 方法二:借助两个栈,循环条件是判断第一个栈非空,第一个栈按左右的顺序压栈,那么出栈顺序为右左,然后第二个栈存放根节点,最后得到的第二个栈整体是中右左的顺序,然后遍历第二个栈,依次出栈存到数组即为左右中的顺序。
代码实现:
- 方法一
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;
}
- 方法二
vector<int> postorderTraversal(TreeNode* root) {
if(root == nullptr)
return {};
stack<TreeNode*> stk;
stack<TreeNode*> stk1;
stk.push(root);
while(!stk.empty()) {
TreeNode* node = stk.top();
stk.pop();
if(node->left) stk.push(node->left);
if(node->right) stk.push(node->right);
stk1.push(node);
}
while(!stk1.empty()) {
vec.push_back(stk1.top()->val);
stk1.pop();
}
return vec;
}
层次遍历
力扣题目链接
题目描述:
给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。
思路:
- 其实是图的广度优先遍历,借助队列一列一列模拟即可。
代码实现
vector<vector<int>> levelOrder(TreeNode* root) {
queue<TreeNode*> que;
vector<vector<int>> results;
int size = 0;
if (root != nullptr) {
que.push(root);
}
while(!que.empty()) {
size = que.size();
vector<int> vec;
for(int i = 0; i < size; i++) {
TreeNode* cur = que.front();
que.pop();
vec.push_back(cur->val);
if (cur->left) que.push(cur->left);
if (cur->right) que.push(cur->right);
}
results.push_back(vec);
}
return results;
}
- BFS递归法遍历
在这里插入代码片