二叉树的3种遍历方法
1.递归遍历二叉树(前中后)
递归思想
思考:构造递归函数
(1)确定递归函数的参数和返回值
void traversal(TreeNode* cur, vector<int>& vec) {
(2)确定终止条件
if (cur == NULL) return;
(3)确定单层递归逻辑
traversal(cur->left,result); //左
result.push_back(cur->vval); //中
traversal(cur->right,result); //右
(4)链式存储的结构体
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
}
144-前序遍历(简单)
题目链接:LeetCode-144
代码:
class Solution {
public:
void traversal(TreeNode* cur, vector<int>& vec){
if(cur == NULL) return;
vec.push_back(cur->val);
traversal(cur->left,vec);
traversal(cur->right,vec);
}
vector<int> preorderTraversal(TreeNode* root) {
vector<int> result;
traversal(root,result);
return result;
}
};
94-中序遍历(简单)
题目链接:LeetCode-94
代码:
class Solution {
public:
void traversal(TreeNode* cur, vector<int>& vec){
if(cur == NULL) return;
traversal(cur->left,vec);
vec.push_back(cur->val);
traversal(cur->right,vec);
}
vector<int> inorderTraversal(TreeNode* root) {
vector<int> result;
traversal(root,result);
return result;
}
};
145-后序遍历(简单)
题目链接:LeetCode-145
代码:
class Solution {
public:
void traversal(TreeNode* cur, vector<int>& vec){
if(cur == NULL) return;
traversal(cur->left,vec);
traversal(cur->right,vec);
vec.push_back(cur->val);
}
vector<int> postorderTraversal(TreeNode* root) {
vector<int> result;
traversal(root,result);
return result;
}
};
2.迭代遍历二叉树(前中后)
迭代思想
思考:本质和递归没有区别,都是利用栈来实现的。
迭代就是模拟压栈和弹栈的过程,不同的递归,压栈和弹栈顺序不同。
144-前序遍历
题目链接:LeetCode-144
迭代过程:1->2->4->5->3->6->7(压栈顺序,先压右在压左)
1压入栈中,弹出1,将3,2压入栈中(先压3在压2)
将2弹出栈中,将4,5压入栈中
弹出4,无子节点,故不压栈,同理弹出5
弹出3,压入7,6
最后弹出6,7结束
代码:
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
if(root == nullptr) return {};
vector<int> result;
stack<TreeNode*> stk;
stk.push(root); //将根结点压栈
while(!stk.empty())
{
TreeNode* cur = stk.top();
stk.pop();
result.push_back(cur->val);
//右子节点先压栈
if(cur->right != nullptr) stk.push(cur->right);
if(cur->left != nullptr) stk.push(cur->left);
}
return result;
}
};
94-中序遍历
题目链接:LeetCode-94
迭代过程:左中右
代码:
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;
}
};
145-后序遍历
题目链接:LeetCode-145
迭代过程:根据前序遍历调整,前:中左右 --(交换左右)> 中右左 --(翻转)>左右中
代码:
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
if(root == nullptr) return {};
vector<int> result;
stack<TreeNode*> stk;
stk.push(root); //将根结点压栈
while(!stk.empty())
{
TreeNode* cur = stk.top();
stk.pop();
result.push_back(cur->val);
//左子节点先压栈
if(cur->left != nullptr) stk.push(cur->left);
if(cur->right != nullptr) stk.push(cur->right);
}
reverse(result.begin(),result.end());
return result;
}
};
3.统一迭代遍历二叉树(前中后)
统一迭代思想
中序思考:若栈顶不为空,弹出栈顶,右中左顺序压栈,中间节点加上NULL,若栈顶不为空,,,循环,达到效果。
144-前序遍历
题目链接:LeetCode-144
代码:
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> result;
stack<TreeNode*> st;
if (root != NULL) st.push(root);
while (!st.empty()) {
TreeNode* node = st.top();
if (node != NULL) {
st.pop(); // 将该节点弹出,避免重复操作,下面再将右中左节点添加到栈中
if (node->right) st.push(node->right); //右
if (node->left) st.push(node->left); //左
st.push(node); //中
st.push(NULL); // 中节点访问过,但是还没有处理,加入空节点做为标记。
} else { // 只有遇到空节点的时候,才将下一个节点放进结果集
st.pop(); // 将空节点弹出
node = st.top(); // 重新取出栈中元素
st.pop();
result.push_back(node->val); // 加入到结果集
}
}
return result;
}
};
94-中序遍历
题目链接:LeetCode-94
代码:
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> result;
stack<TreeNode*> st;
if (root != NULL) st.push(root);
while (!st.empty()) {
TreeNode* node = st.top();
if (node != NULL) {
st.pop(); // 将该节点弹出,避免重复操作,下面再将右中左节点添加到栈中
if (node->right) st.push(node->right); // 添加右节点(空节点不入栈)
st.push(node); // 添加中节点
st.push(NULL); // 中节点访问过,但是还没有处理,加入空节点做为标记。
if (node->left) st.push(node->left); // 添加左节点(空节点不入栈)
} else { // 只有遇到空节点的时候,才将下一个节点放进结果集
st.pop(); // 将空节点弹出
node = st.top(); // 重新取出栈中元素
st.pop();
result.push_back(node->val); // 加入到结果集
}
}
return result;
}
145-后序遍历
题目链接:LeetCode-145
代码:
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> result;
stack<TreeNode*> st;
if (root != NULL) st.push(root);
while (!st.empty()) {
TreeNode* node = st.top();
if (node != NULL) {
st.pop(); // 将该节点弹出,避免重复操作,下面再将右中左节点添加到栈中
st.push(node); //中
st.push(NULL); // 中节点访问过,但是还没有处理,加入空节点做为标记。
if (node->right) st.push(node->right); //右
if (node->left) st.push(node->left); //左
} else { // 只有遇到空节点的时候,才将下一个节点放进结果集
st.pop(); // 将空节点弹出
node = st.top(); // 重新取出栈中元素
st.pop();
result.push_back(node->val); // 加入到结果集
}
}
return result;
}
};