二叉树算法练习
1. 二叉树的深度遍历
递归法 和 迭代法
前序(中左右) 、中序(左中右) 、后序(左右中) 遍历
点击查看代码
#include"../tools.h"
struct TreeNode
{
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
/* 递归法 */
// 前序
void RecursionTraversalFront(const TreeNode* root, vector<int>& ans)
{
if (!root) return;
ans.emplace_back(root->val);
RecursionTraversalFront(root->left, ans);
RecursionTraversalFront(root->right, ans);
}
// 中序
void RecursionTraversalMid(const TreeNode* root, vector<int>& ans)
{
if (!root) return;
RecursionTraversalMid(root->left, ans);
ans.emplace_back(root->val);
RecursionTraversalMid(root->right, ans);
}
// 后序
void RecursionTraversalBack(const TreeNode* root, vector<int>& ans)
{
if (!root) return;
RecursionTraversalBack(root->left, ans);
RecursionTraversalBack(root->right, ans);
ans.emplace_back(root->val);
}
/* 迭代法 */
// 前序
vector<int> TraversalPreOrd(TreeNode* root)
{
vector<int> ans;
stack<TreeNode*> st;
if (root) st.push(root);
while (!st.empty())
{
TreeNode* node = st.top();
if (node)
{
st.pop();
if (node->right) st.push(node->right);
if (node->left) st.push(node->left);
st.push(node);
st.push(nullptr);
}
else
{
st.pop();
ans.emplace_back(st.top()->val);
st.pop();
}
}
return ans;
}
// 中序
vector<int> TraversalInOrd(TreeNode* root)
{
vector<int> ans;
stack<TreeNode*> st;
if (root) st.push(root);
while (!st.empty())
{
TreeNode* node = st.top();
if (node)
{
st.pop();
if (node->right) st.push(node->right);
st.push(node);
st.push(nullptr);
if (node->left) st.push(node->left);
}
else
{
st.pop();
ans.emplace_back(st.top()->val);
st.pop();
}
}
return ans;
}
// 后序
vector<int> TraversalBackOrd(TreeNode* root)
{
vector<int> ans;
stack<TreeNode*> st;
if (root) st.push(root);
while (!st.empty())
{
TreeNode* node = st.top();
if (node)
{
st.push(nullptr);
if (node->right) st.push(node->right);
if (node->left) st.push(node->left);
}
else
{
st.pop();
ans.emplace_back(st.top()->val);
st.pop();
}
}
return ans;
}
/* 调用 */
vector<vector<int>> RecursionTraversal(const TreeNode* root)
{
vector<vector<int>> ans;
vector<int> tmp;
RecursionTraversalFront(root, tmp);
ans.emplace_back(tmp);
tmp.clear();
RecursionTraversalMid(root, tmp);
ans.emplace_back(tmp);
tmp.clear();
RecursionTraversalBack(root, tmp);
ans.emplace_back(tmp);
return ans;
}
vector<vector<int>> IterateTraversal(TreeNode* root)
{
vector<vector<int>> ans;
ans.emplace_back(TraversalPreOrd(root));
ans.emplace_back(TraversalInOrd(root));
ans.emplace_back(TraversalBackOrd(root));
return ans;
}
int main()
{
TreeNode* root = new TreeNode(1);
TreeNode* n1 = new TreeNode(2);
TreeNode* n2 = new TreeNode(3);
root->right = n1;
n1->left = n2;
showArr2D(RecursionTraversal(root));
showArr2D(IterateTraversal(root));
return 0;
}
2. 二叉树层序遍历
给你一个二叉树,请你返回其按 层序遍历 得到的节点值。
(即逐层地,从左到右访问所有节点)。
代码如下:
点击查看代码
#include"../tools.h"
// 迭代法
vector<vector<int>> LayerOrdTraversal(TreeNode* root)
{
queue<TreeNode*> que;
if (root) que.emplace(root);
vector<vector<int>> ans;
while (!que.empty())
{
int size = que.size();
vector<int> vec;
// 每一层
for (int i = 0; i < size; ++i)
{
TreeNode* node = que.front();
que.pop();
vec.emplace_back(node->val);
if (node->left) que.emplace(node->left);
if (node->right) que.emplace(node->right);
}
// 结果存储
ans.emplace_back(vec);
}
return ans;
}
// 递归法
void RecursionLayerOrd(TreeNode* root, vector<vector<int>>& ans, int depth)
{
if (!root) return;
// 第一次进入该层时,初始化层结果
if (ans.size() == depth) ans.push_back(vector<int>());
ans[depth].emplace_back(root->val);
RecursionLayerOrd(root->left, ans, depth + 1);
RecursionLayerOrd(root->right, ans, depth + 1);
}
vector<vector<int>> LayerOrdTraversalRecursion(TreeNode* root)
{
vector<vector<int>> ans;
RecursionLayerOrd(root, ans, 0);
return ans;
}
int main()
{
TreeNode* root = new TreeNode(3);
TreeNode* n1 = new TreeNode(9);
TreeNode* n2 = new TreeNode(20);
TreeNode* n3 = new TreeNode(15);
TreeNode* n4 = new TreeNode(7);
root->left = n1;
root->right = n2;
n2->left = n3;
n2->right = n4;
showArr2D(LayerOrdTraversal(root));
showArr2D(LayerOrdTraversalRecursion(root));
return 0;
}
3. 翻转二叉树
点击查看代码
#include"../tools.h"
// 递归法
TreeNode* RecursionReverse(TreeNode* root)
{
if (!root) return root;
swap(root->left, root->right);
RecursionReverse(root->left);
RecursionReverse(root->right);
return root;
}
// 迭代法
// 深度优先遍历
TreeNode* ReverseDepF(TreeNode* root)
{
stack<TreeNode*> st;
if (root) st.emplace(root);
while (!st.empty())
{
TreeNode* node = st.top();
if (node)
{
st.pop();
if (node->right) st.emplace(node->right);
st.emplace(node);
st.push(nullptr);
if (node->left) st.emplace(node->left);
}
else
{
st.pop();
swap(st.top()->left, st.top()->right);
st.pop();
}
}
return root;
}
// 广度优先遍历
TreeNode* ReverseBroF(TreeNode* root)
{
queue<TreeNode*> que;
if (root) que.emplace(root);
while (!que.empty())
{
int size = que.size();
for (int i = 0; i < size; ++i)
{
TreeNode* node = que.front();
que.pop();
swap(node->left, node->right);
if (node->left) que.emplace(node->left);
if (node->right) que.emplace(node->right);
}
}
return root;
}
int main()
{
TreeNode* root = new TreeNode(4);
TreeNode* left = new TreeNode(2);
TreeNode* right = new TreeNode(7);
root->left = left;
root->right = right;
left->left = new TreeNode(1);
left->right = new TreeNode(3);
right->left = new TreeNode(6);
right->right = new TreeNode(9);
// showTreePreOrd(RecursionReverse(root));
// showTreePreOrd(ReverseDepF(root));
showTreePreOrd(ReverseBroF(root));
return 0;
}
4. 对称二叉树
给定一个二叉树,检查它是否是镜像对称的
点击查看代码
#include"../tools.h"
bool IsMirrorTree(TreeNode* root)
{
// 空返
if (!root) return true;
queue<TreeNode*> que;
que.push(root->left);
que.push(root->right);
while (!que.empty())
{
TreeNode* left = que.front();
que.pop();
TreeNode* right = que.front();
que.pop();
// 左右都为空
if (!left && !right)
continue;
// 左右有一个不为空或者不相等
if ((!left || !right || (left->val != right->val)))
return false;
// 依次存入
que.push(left->left);
que.push(right->right);
que.push(left->right);
que.push(right->left);
}
return true;
}
int main()
{
TreeNode* root = new TreeNode(1);
TreeNode* left = new TreeNode(2);
TreeNode* right = new TreeNode(2);
root->left = left;
root->right = right;
left->left = new TreeNode(3);
left->right = new TreeNode(4);
right->left = new TreeNode(4);
right->right = new TreeNode(3);
cout << IsMirrorTree(root) << endl;
return 0;
}
5. 完全二叉树的节点个数
给出一个完全二叉树,求出该树的节点个数。
示例 1:
输入:root = [1,2,3,4,5,6]
输出:6
示例 2:
输入:root = []
输出:0
示例 3:
输入:root = [1]
输出:1
提示:
树中节点的数目范围是[0, 5 * 10^4]
0 <= Node.val <= 5 * 10^4
题目数据保证输入的树是 完全二叉树
代码如下:
点击查看代码
// 完全二叉树:满二叉树、叶子节点不满,但都在左边
// 节点个数:1 ~ 2^h - 1
// 某层的节点个数:2^(h -1)
#include"../tools.h"
// ~ 普通求法 ~
// 迭代
int getTreeNumIter(TreeNode* root)
{
queue<TreeNode*> que;
if (root) que.emplace(root);
int nums = 0;
while (!que.empty())
{
int size = que.size();
for (int i = 0; i< size; ++i)
{
TreeNode* node = que.front();
que.pop();
nums++;
if (node->left) que.emplace(node->left);
if (node->right) que.emplace(node->right);
}
}
return nums;
}
// 递归
int getTreeNumRecursion(TreeNode* root)
{
if (!root) return 0;
return 1 + getTreeNumRecursion(root->left) + getTreeNumRecursion(root->right);
}
// ~ 完全二叉树性质求法(叶子节点不满,但都在左边) ~
int getTreeNumProperity(TreeNode* root)
{
if (!root) return 0;
int leftN = 0, rightN = 0;
TreeNode* left = root->left;
TreeNode* right = root->right;
while (left)
{
leftN++;
left = left->left;
}
while (right)
{
rightN++;
right = right->right;
}
if (leftN == rightN) // 满二叉树
return (2 << leftN) - 1;
return getTreeNumProperity(root->left) + getTreeNumProperity(root->right) + 1;
}
int main()
{
TreeNode* root = new TreeNode(1);
TreeNode* left = new TreeNode(2);
TreeNode* right = new TreeNode(2);
root->left = left;
root->right = right;
left->left = new TreeNode(3);
left->right = new TreeNode(4);
right->left = new TreeNode(4);
right->right = new TreeNode(3);
cout << getTreeNumRecursion(root) << endl;
cout << getTreeNumIter(root) << endl;
cout << getTreeNumProperity(root) << endl;
return 0;
}
6. 平衡二叉树
给定一个二叉树,判断它是否是高度平衡的二叉树。
本题中,一棵高度平衡二叉树定义为:一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。
示例 1:
给定二叉树 [3,9,20,null,null,15,7]
返回 true
示例 2:
给定二叉树 [1,2,2,3,3,null,null,4,4]
返回 false
代码如下:
点击查看代码
#include"../tools.h"
int getHeight(TreeNode* root)
{
if (!root) return 0;
int leftH = getHeight(root->left);
if (leftH == -1)
return -1;
int rightH = getHeight(root->right);
if (rightH == -1)
return -1;
return abs(rightH - leftH) > 1 ? -1 : 1 + max(leftH, rightH);
}
bool IsBalance(TreeNode* root)
{
return getHeight(root) == -1 ? false : true;
}
int main()
{
TreeNode* root = new TreeNode(1);
TreeNode* left = new TreeNode(2);
TreeNode* right = new TreeNode(2);
root->left = left;
TreeNode* leftL = new TreeNode(3);
TreeNode* leftR = new TreeNode(3);
left->left = leftL;
left->right = leftR;
leftL->left = new TreeNode(4);
leftL->right = new TreeNode(4);
root->right = right;
cout << IsBalance(root) << endl;
return 0;
}
7. 二叉树的所有路径
给定一个二叉树,返回所有从根节点到叶子节点的路径。
说明: 叶子节点是指没有子节点的节点。
代码如下:
点击查看代码
#include"../tools.h"
void traversal(TreeNode* root, string path, vector<string>& ans)
{
path += to_string(root->val);
if (!root->left && !root->right)
{
ans.emplace_back(path);
return;
}
if (root->left)
traversal(root->left, path + "->", ans);
if (root->right)
traversal(root->right, path + "->", ans);
}
vector<string> binaryTreePaths(TreeNode* root) {
if (!root) return {};
vector<string> ans;
string path;
traversal(root, path, ans);
return ans;
}
int main()
{
TreeNode* root = new TreeNode(1);
TreeNode* left = new TreeNode(2);
TreeNode* right = new TreeNode(3);
root->left = left;
root->right = right;
left->right = new TreeNode(5);
showArr(binaryTreePaths(root));
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)