二叉树深度遍历和广度遍历:
深度遍历有 前序、 中序以及 后序
广度遍历即 层次遍历,需要其他数据结构支撑(比如队列)
二叉树的遍历通常采用递归方式,但是有一些题目会要求使用迭代的方式,所以最好都掌握一下。
关于遍历方式的定义和理解就不阐述了。
二叉树节点很简单:
// Definition for a binary tree node.
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
前序遍历
LeetCode第 144 题:二叉树的前序遍历(C++)_qq_32523711的博客-CSDN博客
递归法
class Solution {
public:
vector<int> res;
void preorder(TreeNode* root){
if(!root) return;
res.push_back(root->val);
preorder(root->left);
preorder(root->right);
}
vector<int> preorderTraversal(TreeNode* root) {
if(!root) return res;
preorder(root);
return res;
}
};
迭代法(使用栈)
逻辑很简单,先右后左,利用栈的先进后出性质。
class Solution {
public:
vector<int> res;
vector<int> preorderTraversal(TreeNode* root) {
if(!root) return res;
stack<TreeNode*> s;
s.push(root);
while(!s.empty()){
auto cur = s.top(); s.pop();
res.push_back(cur->val);
if(cur->right) s.push(cur->right);
if(cur->left) s.push(cur->left);
}
return res;
}
};
换种写法,为了和其他的遍历方式保持统一:
二叉树的中序遍历 - 迭代法 - 二叉树的中序遍历 - 力扣(LeetCode),这儿的总结非常好。
//前序:
栈S;
p= root;
while(p || S不空){
while(p){
访问p节点;
p的右子树入S;
p = p的左子树;
}
p = S栈顶弹出;
}
class Solution {
public:
vector<int> res;
vector<int> preorderTraversal(TreeNode* root) {
if(!root) return res;
stack<TreeNode*> s;
auto cur = root;
while(cur || !s.empty()){
while(cur){//保存根节点的值后一直往左走到底
s.push(cur->right);//保存右边
res.push_back(cur->val);//存储根节点的值
cur = cur->left;//往左走
}
cur = s.top(); s.pop();
}
return res;
}
};
中序遍历
LeetCode第 94 题:二叉树的中序遍历(C++)_qq_32523711的博客-CSDN博客
递归法
class Solution {
public:
vector<int> res;
void inorder(TreeNode* root){
if(!root) return;
inorder(root->left);
res.push_back(root->val);
inorder(root->right);
}
vector<int> inorderTraversal(TreeNode* root) {
if(root == NULL) return res;
inorder(root);
return res;
}
};
迭代法(使用栈)
//中序
栈S;
p= root;
while(p || S不空){
while(p){
p入S;
p = p的左子树;
}
p = S.top 出栈;
访问p;//这儿访问
p = p的右子树;
}
class Solution {
public:
vector<int> res;
vector<int> inorderTraversal(TreeNode* root) {
stack<TreeNode*> s;
auto cur = root;
while(cur || !s.empty()){
while(cur){
s.push(cur);
cur = cur->left;
}
cur = s.top(); s.pop();
res.push_back(cur->val);
cur = cur->right;
}
return res;
}
};
后序遍历
LeetCode第 145 题:二叉树的后序遍历(C++)_zj-CSDN博客
递归法
class Solution {
public:
vector<int> res;
void postorder(TreeNode* root){
if(!root) return;
postorder(root->left);
postorder(root->right);
res.push_back(root->val);
}
vector<int> postorderTraversal(TreeNode* root) {
if(!root) return res;
postorder(root);
return res;
}
};
迭代法
//后序
栈S;
p= root;
while(p || S不空){
while(p){//和前序相反
访问p节点;
p的左子树入S;
p = p的右子树;
}
p = S栈顶弹出;
}
结果序列逆序;
class Solution {
public:
vector<int> res;
vector<int> postorderTraversal(TreeNode* root) {
if(!root) return res;
stack<TreeNode*> s;
auto cur = root;
//前序根左右,后续左右根,所以先得到根右左,然后反转得到左右根
while(cur || !s.empty()){
while(cur){//这儿和前序的反过来就行了
s.push(cur->left);
res.push_back(cur->val);
cur = cur->right;
}
cur = s.top(); s.pop();
}
reverse(res.begin(), res.end());
return res;
}
};
层次遍历
LeetCode第 102 题:二叉树的层次遍历(C++)_qq_32523711的博客-CSDN博客
上述题目是有额外要求的,如果只要求返回一维数组,直接使用队列就可以啦,也不需要进行层次判断。