自学内容网 自学内容网

二叉树面试题(C 语言)

1. 单值二叉树

题目描述: 如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树。只有给定的树是单值二叉树时,才返回 true;否则返回 false。

示例 1:
在这里插入图片描述
输入:[1,1,1,1,1,null,1]
输出:true

示例 2:
在这里插入图片描述
输入:[2,2,2,5,2]
输出:false

提示:

  1. 给定树的节点数范围是 [1, 100]。
  2. 每个节点的值都是整数,范围为 [0, 99]

题目OJ链接: link

解题思路: 运用递归的思想,把二叉树分成一个个小树。根节点和左右孩子比较,若相同则左右孩子继续和它们的孩子比较,直到空树。遇到空树需要返回 true,因为遇到空树了就证明你这一整棵树都满足单值条件。其中有一组不相同就返回 false,全部相同返回 true。

代码如下:

bool isUnivalTree(struct TreeNode* root) {
    // 空树
    if (NULL == root)
        return true;
    // 根节点和孩子比较
    if (root->left && root->left->val != root->val)
        return false;
    if (root->right && root->right->val != root->val)
        return false;
    // 继续比较左子树和右子树
    return isUnivalTree(root->left)
        && isUnivalTree(root->right);
}

2. 相同的树

题目描述: 给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

示例 1:
在这里插入图片描述
输入:p = [1,2,3], q = [1,2,3]
输出:true

示例 2:
在这里插入图片描述
输入:p = [1,2], q = [1,null,2]
输出:false

示例 3:
在这里插入图片描述
输入:p = [1,2,1], q = [1,1,2]
输出:false

提示:

  1. 两棵树上的节点数目都在范围 [0, 100] 内
  2. -104 <= Node.val <= 104

题目OJ链接: link

解题思路: 首先判断根节点,然后再判断左子树,再判断右子树,直到两边都是空树。全部都满足才是相同的树,返回 true;一个地方不满足都是不相同的树,返回 false。

代码如下:

bool isSameTree(struct TreeNode* p, struct TreeNode* q) {
    // 空树判断
    if (NULL == p && NULL == q)
        return true;
    // 有一颗空树
    if (NULL == p || NULL == q)
        return false;
    // 根节点不同
    if (p->val != q->val)
        return false;
    // 左右子树
    return isSameTree(p->left, q->left)
        && isSameTree(p->right, q->right);
}

3. 对称二叉树

题目描述: 给你一个二叉树的根节点 root , 检查它是否轴对称。

示例 1:
在这里插入图片描述
输入:root = [1,2,2,3,4,4,3]
输出:true

示例 2:
在这里插入图片描述
输入:root = [1,2,2,null,3,null,3]
输出:false

提示:

  1. 树中节点数目在范围 [1, 1000] 内
  2. -100 <= Node.val <= 100

题目OJ链接: link

解题思路: 对称二叉树根节点的左右子树对称,那么左子树的左子树应该和右子树的右子树对称,左子树的右子树应该和右子树的左子树对称。直到两边都是空树,返回 true。只要有一个不满足,就返回 false。

代码如下:

typedef struct TreeNode TreeNode;

// 左右子树对称判断
bool isSymmetricLeftAndRight(TreeNode* left, TreeNode* right)
{
    // 都是空树
    if (NULL == left && NULL == right)
        return true;
    // 有一颗空树
    if (NULL == left || NULL == right)
        return false;
    // 值不相同
    if (left->val != right->val)
        return false;
    // 对称树比较
    return isSymmetricLeftAndRight(left->left, right->right)
        && isSymmetricLeftAndRight(left->right, right->left);
}

bool isSymmetric(struct TreeNode* root) {
    return isSymmetricLeftAndRight(root->left, root->right);
}

4. 二叉树的前序遍历

题目描述: 给你二叉树的根节点 root ,返回它节点值的 前序 遍历。

示例 1:

输入:root = [1,null,2,3]

输出:[1,2,3]

解释:
在这里插入图片描述

示例 2:

输入:root = [1,2,3,4,5,null,8,null,null,6,7,9]

输出:[1,2,4,5,6,7,3,8,9]

解释:
在这里插入图片描述

示例 3:

输入:root = []

输出:[]

示例 4:

输入:root = [1]

输出:[1]

提示:

  1. 树中节点数目在范围 [0, 100] 内
  2. -100 <= Node.val <= 100

题目OJ链接: link

解题思路: 本题需要动态开辟一个数组用来存储二叉树的前序遍历进行返回,第二个参数需要返回开辟数组的大小。第一步需要计算二叉树的节点个数,然后再开辟空间,返回二叉树的前序遍历。

代码如下:

typedef struct TreeNode TreeNode;

// 返回二叉树节点的个数
size_t TreeSize(TreeNode* root)
{
    // 空树
    if (NULL == root)
        return 0;
    // 返回 1+左右节点的个数
    return 1 + TreeSize(root->left) + TreeSize(root->right);
}

// 记录二叉树的前序遍历
void GetPreOrder(TreeNode* root, int* arr, int* pi)
{
    // 空树
    if (NULL == root)
        return;
    // 记录根节点
    arr[(*pi)] = root->val;
    ++(*pi);
    // 记录左子树
    GetPreOrder(root->left, arr, pi);
    // 记录右子树
    GetPreOrder(root->right, arr, pi);
}

int* preorderTraversal(struct TreeNode* root, int* returnSize) {
    // 获得节点个数
    size_t n = TreeSize(root);
    *returnSize = n;
    // 开辟空间
    int* arr = (int*)malloc(sizeof(int)*n);
    // 获得前序遍历
    int i = 0;
    GetPreOrder(root, arr, &i);
    // 返回
    return arr;
}

5. 二叉树的中序遍历

本题和二叉树的前序遍历相似,只给出题目链接和代码。

题目OJ链接: link

代码如下:

typedef struct TreeNode TreeNode;

// 返回二叉树的节点个数
size_t TreeSize(TreeNode* root)
{
    // 空树
    if (NULL == root)
        return 0;
    // 返回 1 + 左右子树节点个数
    return 1 + TreeSize(root->left) + TreeSize(root->right);
}

// 获得二叉树中序遍历
void GetInOrder(TreeNode* root, int* arr, int* pi)
{
    // 空树
    if (NULL == root)
        return;
    // 左子树
    GetInOrder(root->left, arr, pi);
    // 记录根节点
    arr[*pi] = root->val;
    ++*pi;
    // 右子树
    GetInOrder(root->right, arr, pi);
}

int* inorderTraversal(struct TreeNode* root, int* returnSize) {
    // 获得节点个数
    size_t n = TreeSize(root);
    *returnSize = n;
    // 开辟空间
    int* arr = (int*)malloc(sizeof(int)*n);
    // 获得中序遍历
    int i = 0;
    GetInOrder(root, arr, &i);
    // 返回
    return arr;
}

6. 二叉树的后序遍历

题目OJ链接: link

代码如下:

typedef struct TreeNode TreeNode;

// 返回二叉树节点个数
size_t TreeSize(TreeNode* root)
{
    // 空树
    if (NULL == root)
        return 0;
    // 返回 1 + 左右子树节点个数
    return 1 + TreeSize(root->left) + TreeSize(root->right);
}

// 返回二叉树的后序遍历
void GetPostOrder(TreeNode* root, int* arr, int* pi)
{
    // 空树
    if (NULL == root)
        return;
    // 左子树
    GetPostOrder(root->left, arr, pi);
    // 右子树
    GetPostOrder(root->right, arr, pi);
    // 记录根节点
    arr[*pi] = root->val;
    ++*pi;
}

int* postorderTraversal(struct TreeNode* root, int* returnSize) {
    // 获得节点个数
    size_t n = TreeSize(root);
    *returnSize = n;
    // 开辟对应空间
    int* arr = (int*)malloc(sizeof(int)*n);
    // 获得中序遍历
    int i = 0;
    GetPostOrder(root, arr, &i);
    // 返回
    return arr;
}

7. 另一颗树的子树

题目描述: 给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false 。

二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。

示例 1:
在这里插入图片描述
输入:root = [3,4,5,1,2], subRoot = [4,1,2]
输出:true

示例 2:
在这里插入图片描述
输入:root = [3,4,5,1,2,null,null,null,null,0], subRoot = [4,1,2]
输出:false

提示:

  1. root 树上的节点数量范围是 [1, 2000]
  2. subRoot 树上的节点数量范围是 [1, 1000]
  3. -104 <= root.val <= 104
  4. -104 <= subRoot.val <= 104

题目OJ链接: link

解题思路: 把当前数与之比较,不相同则比较子树,子树按照这个方法继续比较,直到空树。其中有一颗树与之相同就返回 false。

代码如下:

typedef struct TreeNode TreeNode;

// 判断两棵树是否相同
bool isSameTree(TreeNode* root1, TreeNode* root2)
{
    // 都是空树
    if (NULL == root1 && NULL == root2)
        return true;
    // 有一颗空树
    if (NULL == root1 || NULL == root2)
        return false;
    // 值不相同
    if (root1->val != root2->val)
        return false;
    // 左右子树比较
    return isSameTree(root1->left, root2->left)
        && isSameTree(root1->right, root2->right);
}

bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot) {
    // 空树
    if (NULL == root)
        return false;
    // 当前树判断
    if (isSameTree(root, subRoot))
        return true;
    // 左右子树判断
    return isSubtree(root->left, subRoot)
        || isSubtree(root->right, subRoot);
}

8. 通过前序遍历返回中序遍历

题目描述:
编一个程序,读入用户输入的一串先序遍历字符串,根据此字符串建立一个二叉树(以指针方式存储)。 例如如下的先序遍历字符串: ABC##DE#G##F### 其中“#”表示的是空格,空格字符代表空树。建立起此二叉树以后,再对二叉树进行中序遍历,输出遍历结果。

输入描述:
输入包括1行字符串,长度不超过100。

输出描述:
可能有多组测试数据,对于每组数据, 输出将输入字符串建立二叉树后中序遍历的序列,每个字符后面都有一个空格。 每个输出结果占一行。

示例1
输入:
abc##de#g##f###
输出:
c b e g d f a

题目OJ链接: link

解题思路: 首先根据前序遍历构建出这颗二叉树,先构建根节点然后构建左子树,再构建右子树,如此往复,直到空树。再通过构建的二叉树返回其中序遍历。

代码如下:

#include <stdio.h>
#include <stdlib.h>

// 类型声明
typedef char DataType;

// 二叉树节点声明
typedef struct TreeNode
{
    DataType val;
    struct TreeNode* left;
    struct TreeNode* right;
}TreeNode;

// 构建二叉树
TreeNode* CreateTree(char* tmp, int* pi)
{
    // 空树
    if ('#' == tmp[*pi])
    {
        ++(*pi);
        return NULL;
    }
    // 构建根节点
    TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode));
    root->val = tmp[*pi];
    ++(*pi);
    // 构建左右子树
    root->left = CreateTree(tmp, pi);
    root->right = CreateTree(tmp, pi);
    // 返回根节点
    return root;
}

// 中序遍历
void InOrder(TreeNode* root)
{
    // 空树
    if (NULL == root)
        return;
    // 左子树
    InOrder(root->left);
    // 打印根节点
    printf("%c ", root->val);
    // 右子树
    InOrder(root->right);
}

int main() {
    
    // 所需变量
    char tmp[101];
    // 输入
    while (scanf("%s", tmp) != EOF)
    {
        // 构建二叉树
        int i = 0;
        TreeNode* root = CreateTree(tmp, &i);
        // 中序遍历
        InOrder(root);
    }

    return 0;
}

原文地址:https://blog.csdn.net/weixin_70742989/article/details/143699742

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!