- 满二叉树:顾名思义就是二叉树的所有节点都是有值的,没有空节点,如果二叉树深度为 $k$,那么满二叉树有 $2^k-1$ 个节点
- 完全二叉树:除了最底层节点没有填满外,其余每层节点都填满了,且最底层节点一定是从左到右填
- 二叉搜索树:二叉搜索树的中序遍历是从小到大排序的
- 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值
- 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值
- 它的左、右子树也分别为二叉排序树
- 平衡二叉搜索树:平衡二叉搜索树要么是空树,要么其左右两个子树的高度差不超过 $1$,并且左右两个子树都是平衡二叉搜索树
C++中map、set、multimap,multiset的底层实现都是平衡二叉搜索树
- 二叉树的遍历方式:
- 前序遍历(根节点->左子树->右子树)
- 中序遍历(左子树->根节点->右子树)
- 后序遍历(左子树->右子树->根节点)
- 层序遍历
- 二叉树的定义:
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x): val(x), left(NULL), right(NULL) {}
}*root;
vector <int> res;
vector<int> main(TreeNode* root){
dfs(root);
return res;
}
void dfs(TreeNode* root){
if (!root) return;
res.push_back(root->val);
dfs(root->left);
dfs(root->right);
}
vector <int> res;
vector<int> main(TreeNode* root){
dfs(root);
return res;
}
void dfs(TreeNode* root){
if (!root) return;
dfs(root->left);
res.push_back(root->val);
dfs(root->right);
}
vector <int> res;
vector<int> main(TreeNode* root){
dfs(root);
return res;
}
void dfs(TreeNode* root){
if (!root) return;
dfs(root->left);
dfs(root->right);
res.push_back(root->val);
}
- 思路:二叉树的迭代遍历一般用栈来存储
- 初始化栈
- 当前节点赋值为根节点
- 将根节点和所有左子树入栈并加入答案直至当前节点为空
- 每弹出一个栈顶元素就到达当前节点的右子树
- 代码模板 1
stack<TreeNode*> stk;
vector<int> res;
auto cur = root;
while (cur || stk.size()){
while (cur){
res.push_back(cur->val);
stk.push(cur);
cur = cur->left;
}
auto tmp = stk.top();
stk.pop();
cur = tmp->right;
}
stack<TreeNode*> stk;
vector<int> res;
if (root) stk.push(root);
while (stk.size()){
auto cur = stk.top();
stk.pop();
res.push_back(cur->val);
if (cur->right) stk.push(cur->right);
if (cur->left) stk.push(cur->left);
}
- 思路:与前序遍历的模板 1 相似,区别是前序遍历中在找树的左底部的过程中记录答案,而中序遍历是找到左底部再开始记录答案
- 代码模板
stack<TreeNode*> stk;
vector<int> res;
auto cur = root;
while (cur || stk.size()){
while (cur){
stk.push(cur);
cur = cur->left;
}
auto tmp = stk.top();
stk.pop();
res.push_back(tmp->val);
cur = tmp->right;
}
- 思路:与前序遍历的模板 1 类似
栈是先进后出的顺序,如果是后序遍历,输出为左->右->中,和前序遍历中->左->右相比,可以在前序遍历的基础上将输入改为中->右->左,再将答案数组反转即为左->右->中
- 代码模板 1
stack<TreeNode*> stk;
vector<int> res;
auto cur = root;
while (cur || stk.size()){
while (cur){
stk.push(cur);
res.push_back(cur->val);
cur = cur->right;
}
auto tmp = stk.top();
stk.pop();
cur = tmp->left;
}
reverse(res.begin(), res.end());
stack<TreeNode*> stk;
vector<int> res;
if (root) stk.push(root);
while (stk.size()){
auto cur = stk.top();
stk.pop();
res.push_back(cur->val);
if (cur->left) stk.push(cur->left);
if (cur->right) stk.push(cur->right);
}
- 思路:二叉树的前中后序遍历都是用深度优先搜索的方法(dfs)主要使用栈实现,层序遍历是广度优先搜索主要使用队列实现
- 常规解法:
- 初始化队列
- 将根节点加入队列中
- 当队列不为空时,弹出队头元素,加入到答案中
- 如果左子树非空,左子树加入队列
- 如果右子树非空,右子树加入队列
- 代码模板
queue<TreeNode*> q;
vector<int> res;
q.push(root);
while (q.size()){
int n = q.size();
for (int i = 0; i < n; i ++){
auto cur = q.front();
q.pop();
res.push_back(cur->val);
if (cur->left) q.push(cur->left);
if (cur->right) q.push(cur->right);
}
}
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
// 递归(终止条件)
if (!root) return root;
// 前序遍历(递归解法)
swap(root->left, root->right);
invertTree(root->left);
invertTree(root->right);
// 递归返回值
return root;
}
};
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
// 递归(终止条件)
if (!root) return root;
// 后序遍历(递归解法)
invertTree(root->left);
invertTree(root->right);
swap(root->left, root->right);
// 递归返回值
return root;
}
};
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
// 层序遍历模板
queue<TreeNode*> q;
if (root) q.push(root);
while (q.size()){
int n = q.size();
for (int i = 0; i < n; i ++){
auto c = q.front();
q.pop();
swap(c->left, c->right);
if (c->left) q.push(c->left);
if (c->right) q.push(c->right);
}
}
return root;
}
};
class Solution {
public:
vector<int> res;
vector<int> preorder(Node* root) {
// 递归终止条件
if (!root) return res;
// 前序遍历
res.push_back(root->val);
for (auto c: root->children) preorder(c);
return res;
}
};
class Solution {
public:
vector<int> preorder(Node* root) {
// 与前序遍历常规解法相似
stack<Node*> stk;
vector<int> res;
if (root) stk.push(root);
while (stk.size()){
auto c = stk.top();
stk.pop();
res.push_back(c->val);
for (int i = c->children.size() - 1; i >= 0; i --){
stk.push(c->children[i]);
}
}
return res;
}
};
class Solution {
public:
vector<int> res;
vector<int> postorder(Node* root) {
// 递归终止条件
if (!root) return res;
// 后序遍历
for (auto c: root->children) postorder(c);
res.push_back(root->val);
return res;
}
};
class Solution {
public:
vector<int> postorder(Node* root) {
// 与后序遍历常规解法类似
stack<Node*> stk;
vector<int> res;
if (root) stk.push(root);
while (stk.size()){
auto c = stk.top();
stk.pop();
res.push_back(c->val);
for (int i = 0; i < c->children.size(); i ++){
stk.push(c->children[i]);
}
}
reverse(res.begin(), res.end());
return res;
}
};