二叉树
理论基础
- 次序关系 前中后序 ( VLR, LVR, LRV )
VLR: 前表示根节点在前面,遍历顺序即中左右
LVR: 中表示根节点在中间,遍历顺序即左中右
LRV: 后表示根节点在后面,遍历顺序即左右中
- 遍历方式
DFS (深度优先遍历)- 先往深处走,遇到叶子节点再往回走 :前中后序遍历
BFS(广度优先遍历)- 一层一层遍历:层次遍历
- 二叉树节点构造
struct TreeNode{int val;TreeNode left;TreeNode right;TreeNode (int x): val(x), left(NULL), right(NULL);
}
一、递归遍历
1. 前序遍历
给你二叉树的根节点 root
,返回它节点值的 前序 遍历。
144. 二叉树的前序遍历 - 力扣(LeetCode)
题解
class Solution {
public:void traverse(TreeNode * cur, vector<int> &result){if(cur == nullptr) return;result.push_back(cur->val);traverse(cur->left, result);traverse(cur->right, result);}vector<int> preorderTraversal(TreeNode* root) {vector<int> result;traverse(root, result);return result;}
};
2. 后序遍历
给你二叉树的根节点 root
,返回它节点值的 后序 遍历。
145. 二叉树的后序遍历 - 力扣(LeetCode)
题解
class Solution {
public:void traverse(TreeNode * cur, vector<int> &result){if(cur == nullptr) return;traverse(cur->left, result);traverse(cur->right, result);result.push_back(cur->val);}vector<int> postorderTraversal(TreeNode* root) {vector<int> result;traverse(root, result);return result;}
};
3. 中序遍历
给你二叉树的根节点 root
,返回它节点值的 中序 遍历。
94. 二叉树的中序遍历 - 力扣(LeetCode)
题解
class Solution {
public:void traverse(TreeNode * cur, vector<int> &result){if(cur == nullptr){return ;}traverse(cur->left, result);result.push_back(cur->val);traverse(cur->right, result);}vector<int> inorderTraversal(TreeNode* root) {vector<int> result;traverse(root, result);return result;}
};
二、非递归遍历
知识点
- 非递归使用栈,先进后出
1. 前序遍历
给你二叉树的根节点 root
,返回它节点值的 前序 遍历。
144. 二叉树的前序遍历 - 力扣(LeetCode)
题解
class Solution {
public:vector<int> preorderTraversal(TreeNode* root) {stack<TreeNode*> stk;vector<int> result;if (root == nullptr) return result;stk.push(root);while(!stk.empty()){TreeNode *tmp = stk.top();stk.pop();if(tmp != nullptr) result.push_back(tmp->val); // 中else continue;stk.push(tmp->right); // 右stk.push(tmp->left); // 左}return result;}
};
2. 后序遍历
给你二叉树的根节点 root
,返回它节点值的 后序 遍历。
与前序遍历相似,前序遍历非递归是中右左
修改右左位置为左右,那么就是中左右,再反转成为右左中
145. 二叉树的后序遍历 - 力扣(LeetCode)
题解
class Solution {
public:vector<int> postorderTraversal(TreeNode* root) {stack<TreeNode*> stk;vector<int> result;if(root == nullptr) return result;stk.push(root);while(!stk.empty()){TreeNode *tmp = stk.top();stk.pop();if(tmp != nullptr) result.push_back(tmp->val);else continue;stk.push(tmp->left);stk.push(tmp->right);} reverse(result.begin(), result.end());// 没有返回值,直接修改原容器return result;}
};
3. 中序遍历
给你二叉树的根节点 root
,返回它节点值的 中序 遍历。
94. 二叉树的中序遍历 - 力扣(LeetCode)
题解
class Solution {
public:vector<int> inorderTraversal(TreeNode* root) {stack<TreeNode*> stk;vector<int> result;TreeNode *cur = root;while(cur != nullptr || !stk.empty()){if(cur != nullptr){stk.push(cur);cur = cur->left;}else{cur = stk.top(); stk.pop();result.push_back(cur->val);cur = cur->right;}}return result;}
};
三、二叉树层序遍历
知识点
- 使用一个队列来存储每一次遍历的元素,size的设置则是记录当前层有多少个元素
- 使用一维数组记录每一层的元素,使用二维数组来记录整棵树
1. 二叉树层次遍历
102. 二叉树的层序遍历 - 力扣(LeetCode)
class Solution {
public:vector<vector<int>> levelOrder(TreeNode* root) {queue<TreeNode*> q; vector<vector<int>> result;if(root == nullptr) return result;q.push(root);while(!q.empty()){int size = q.size();vector<int> vec;while(size--){TreeNode *node = q.front();q.pop();vec.push_back(node->val);if(node->left) q.push(node->left);if(node->right) q.push(node->right);}result.push_back(vec);} return result;}
};
2. 二叉树层次遍历II
107. 二叉树的层序遍历 II - 力扣(LeetCode)
class Solution {
public:vector<vector<int>> levelOrderBottom(TreeNode* root) {vector<vector<int>> result;queue<TreeNode*> q;if(root == nullptr) return result;q.push(root);while(!q.empty()){vector<int> vec;int size = q.size();while(size--){TreeNode * node = q.front();q.pop();vec.push_back(node->val);if(node->left) q.push(node->left);if(node->right) q.push(node->right);}result.push_back(vec);}reverse(result.begin(), result.end());return result;}
};
3. 二叉树的右视图
给定一个二叉树的 根节点 root
,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
199. 二叉树的右视图 - 力扣(LeetCode)
class Solution {
public:vector<int> rightSideView(TreeNode* root) {queue<TreeNode*> q;vector<int>result;if(root == nullptr) return result;q.push(root);while(!q.empty()){int size = q.size();vector<int> vec;while(size--){TreeNode *node = q.front();q.pop();vec.push_back(node->val);if(node->left) q.push(node->left);if(node->right) q.push(node->right);}result.push_back(vec.back());}return result;}
};
四、翻转二叉树
题目
给你一棵二叉树的根节点 root
,翻转这棵二叉树,并返回其根节点。
递归三步走:
- 确定递归函数的参数和返回值
参数就是传入的指针,返回根据题目要求是root节点
- 确定终止条件
节点为空则返回
- 单层递归逻辑
前序遍历和后序遍历都可以
226. 翻转二叉树 - 力扣(LeetCode)
题解
class Solution {
public:TreeNode* invertTree(TreeNode* root) {// 根节点为空if(root == nullptr) return root;// 迭代swap(root->right, root->left);invertTree(root->left);invertTree(root->right);return root;}
};