文章分为两个部分:
1、二叉树遍历(先中后,层序)
2、二叉树深度(max,min)
实现方法又分两个部分:
1、递归
2、迭代
拓展题目:N叉树相关题目
下面是leetcode上的相关题目:
二叉树的遍历(迭代)
注意使用迭代法实现二叉树的遍历时需要“反着来”,以先序遍历为例,先序遍历的顺序为:中->左->右,由于栈的特性(先入后出)入栈顺序就是:中->右->左。后序的输出的时候需要翻转数组(可以思考为什么)
//先序遍历
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;
}
};
//中序遍历
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;
}
};
//后序遍历
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;
}
};
//层序遍历
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
// 创建一个二维数组作为返回值
vector<vector<int>> res;
// 创建一个队列用来存储root
queue<TreeNode*> que;
// 判断根节点是不是为空
if(root!= nullptr){
que.push(root);
}
while(!que.empty()){
int size = que.size();
// 创建一个用来暂时存储一维数组的vector
vector<int> vec;
for(int i=0;i<size;i++){
// 创建一个新的节点来承接que中的第一个数据
TreeNode* node = que.front();
// 将第一个数据pop
que.pop();
// 在一维数组中添加数据
vec.push_back(node->val);
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
}
res.push_back(vec);
}
return res;
}
};
二叉树的遍历(递归)
递归需要知道的三个条件:
1、递归函数的参数以及返回值,这里需要遍历二叉树,所以二叉树必不可少成为参数之一,还需要有一个能被修改且从外部传进来的参数存储遍历后的二叉树数组,所以引入例如以个一维向量;
void postorder(TreeNode* root,vector<int>& res)
2、终止条件
当根节点(遍历到的节点为空时就不再遍历)
3、每一层的递归逻辑
class Solution {
public:
//递归函数(函数的参数,注意这个函数返回值为空)
void postorder(TreeNode* root,vector<int>& res) {
if(!root) return ;//递归终止条件
res.push_back(root->val);
postorder(root->left,res);
//中序遍历
//res.push_back(root->val);
postorder(root->right,res);
//后序遍历
//res.push_back(root->val);
}
vector<int> postorderTraversal(TreeNode* root) {
vector<int> res;
//这里!!!!需要执行完函数之后再return!!!
postorder(root,res);
return res;
}
};
没写完。。下次再写(2022.3.9)
求二叉树深度(递归)
求二叉树的深度时考虑下面的情况,如下图所示,该二叉树的最小深度和最大深度可以看出来(min=2,max=3)
现在换一颗二叉树呢?
上面图片中最小深度和最大深度又是多少呢?
max=5
min=1
好像哪里不太对劲?
什么是二叉树的深度呢?
二叉树的深度是从根节点到最近叶子节点的最短(长)路径上的节点数量。
这句话要怎么理解呢?
首先计算深度是根据叶子节点来的,除非是一颗秃树(只有根节点,叶子节点才是根节点);
其次最短路径,看下图,这个二叉树有三条路径,最短的就是1;
也就是计算这个叶子节点到根节点的最小深度。
所以这里就有了实现求深度的方法:
//求二叉树的深度(最大深度)
class Solution {
public:
//递归函数,函数参数以及返回值
int maxDepth(TreeNode* root) {
//终止条件,如果根节点为空则终止递归
if (!root) return 0;
//单次递归的逻辑
int left_len=maxDepth(root->left);
int right_len=maxDepth(root->right);
//返回值
return 1+max(left_len,right_len);
}
};
//最小深度
class Solution {
public:
int minDepth(TreeNode* root) {
if (!root) return 0;
//多了判断是否有一个子树不存在
if(root->left==nullptr && root->right!=nullptr){
return 1+minDepth(root->right);
}
if(root->left!=nullptr && root->right==nullptr){
return 1+minDepth(root->left);
}
return 1+min(minDepth(root->left),minDepth(root->right));
}
};