二叉树算法练习

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. 二叉树层序遍历

给你一个二叉树,请你返回其按 层序遍历 得到的节点值。
(即逐层地,从左到右访问所有节点)。
image

代码如下:

点击查看代码
#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. 翻转二叉树

image

点击查看代码
#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. 对称二叉树

给定一个二叉树,检查它是否是镜像对称的
image

点击查看代码
#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. 二叉树的所有路径

给定一个二叉树,返回所有从根节点到叶子节点的路径。
说明: 叶子节点是指没有子节点的节点。
image

代码如下:

点击查看代码
#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;
}
posted @   bok_tech  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
  1. 1 翻云覆雨 BLL
  2. 2 与我无关 阿冗
  3. 3 想去海边 夏日入侵企划
  4. 4 没有理想的人不伤心 新裤子
  5. 5 生活因你而火热 新裤子
想去海边 - 夏日入侵企划
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.
点击右上角即可分享
微信分享提示