Day 14 树
一、基础知识
1、二叉树的种类
- 满二叉树
- 完全二叉树
- 二叉搜索树
- 平衡二叉搜索树
2、二叉树的存储方式
- 顺序存储结构
- 链式存储结构
3、二叉树的遍历方式
- 深度优先遍历:先往深走,遇到叶子节点再往回走。
- 广度优先遍历:一层一层的去遍历。
从深度优先遍历和广度优先遍历进一步拓展,才有如下遍历方式:
深度优先遍历
1、前序遍历(中左右)(递归法,迭代法)
2、中序遍历(左中右)(递归法,迭代法)
3、后序遍历(左右中)(递归法,迭代法)
广度优先遍历
层次遍历(迭代法)
4、二叉树的定义
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
详细请看代码随想录文章
二、力扣相关例题
1、递归遍历
递归算法的三个要素:
- 确定递归函数的参数和返回值: 确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数,并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。
- 确定终止条件: 写完了递归算法,运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出。
- 确定单层递归的逻辑: 确定每一层递归需要处理的信息。在这里也就会重复调用自己来实现递归的过程。
144. 二叉树的前序遍历
给你二叉树的根节点 root ,返回它节点值的 前序 遍历。
示例 :
输入:root = [1,null,2,3]
输出:[1,2,3]
class Solution {
public:
void pretravalsal (TreeNode* root, vector<int> &vec) {
if (root == NULL) {
return ;
}
//中左右
vec.push_back(root->val);
pretravalsal(root->left, vec);
pretravalsal(root->right, vec);
}
vector<int> preorderTraversal(TreeNode* root) {
vector<int> result;
pretravalsal(root, result);
return result;
}
};
94. 二叉树的中序遍历
给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。
示例 :
输入:root = [1,null,2,3]
输出:[1,3,2]
class Solution {
public:
void intravalsal(TreeNode* root, vector<int> &vec) {
if (root == NULL) {
return ;
}
//左中右
intravalsal(root->left, vec);
vec.push_back(root->val);
intravalsal(root->right, vec);
}
vector<int> inorderTraversal(TreeNode* root) {
vector<int> result;
intravalsal(root, result);
return result;
}
};
145. 二叉树的后序遍历
给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。
示例 :
输入:root = [1,null,2,3]
输出:[1,3,2]
class Solution {
public:
void posttravalsal(TreeNode* root, vector<int> &vec) {
if (root == NULL) {
return ;
}
//左右中
posttravalsal(root->left, vec);
posttravalsal(root->right, vec);
vec.push_back(root->val);
}
vector<int> postorderTraversal(TreeNode* root) {
vector<int> result;
posttravalsal(root, result);
return result;
}
};
2、迭代遍历
144. 二叉树的前序遍历
给你二叉树的根节点 root ,返回它节点值的 前序 遍历。
示例 :
输入:root = [1,null,2,3]
输出:[1,2,3]
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> result;
//这里的栈特别要注意,存放的是节点,所以是TreeNode
stack<TreeNode*> sta;
sta.push(root);
while(!sta.empty()) {
TreeNode* node = sta.top();
sta.pop();
if (node != NULL) {
//如果节点不为空,则将数值传入result数组
result.push_back(node->val);
} else {
//若为空,则跳过
continue;
}
//先放入右孩子,后放入左孩子
sta.push(node->right);
sta.push(node->left);
}
return result;
}
};
94. 二叉树的中序遍历
给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。
示例 :
输入:root = [1,null,2,3]
输出:[1,3,2]
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> result;
stack<TreeNode*> sta;
TreeNode* cur = root;
while (cur != NULL || !sta.empty()) {
if (cur != NULL) {
sta.push(cur);
cur = cur -> left;
} else {
cur = sta.top();
sta.pop();
result.push_back(cur -> val);
cur = cur -> right;
}
}
return result;
}
};
145. 二叉树的后序遍历
给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。
示例 :
输入:root = [1,null,2,3]
输出:[1,3,2]
关键:
后序:左右中
前序:中左右
中左右→中右左(调换左右顺序)→左右中(反转数组数值)
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> result;
stack<TreeNode*> sta;
sta.push(root);
while (!sta.empty()) {
TreeNode* node;
node = sta.top();
sta.pop();
if (node != NULL) {
result.push_back(node->val);
} else {
continue;
}
sta.push(node->left);
sta.push(node->right);
}
reverse(result.begin(), result.end());
return result;
}
};