【二叉树基础oj题型总结-C语言实现】

本文详细介绍了使用C语言实现的二叉树基础算法,涵盖了单值二叉树、相同树的判断、对称二叉树、前序遍历、子树查找等经典问题,通过递归和迭代的方法解决。此外,还提供了二叉树的创建及中序遍历的实现。内容详实,适合二叉树算法的学习和巩固。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

请添加图片描述



前言

本文总结二叉树基础oj题型总结-C语言实现。


一、力扣965. 单值二叉树

// 第一遍自己写:(一边写,一边画图验证)
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */


bool isUnivalTree(struct TreeNode* root)
{
    
    if (NULL == root)
    {
        return true;// NULL为true,根据画图得
    }

    if ((NULL != root->left) && (root->val != root->left->val)) //如果相等就返回true,那就错了,必须所有都相等才返回true
    {
        return false;
    }

    if ((NULL != root->right) && (root->val != root->right->val))
    {
        return false;
    }

    // 每个根跟它的左右孩子都相等,返回true
    return isUnivalTree(root->left) && isUnivalTree(root->right); // &&如果左为false,右不执行

}


// 方法二:遍历二叉树,用根得值和所有结点比一遍(本质和方法1相同)

二、力扣100. 相同的树

// 100. 相同的树


// 第一遍自己写:(一边写,一边画图验证)(同讲)
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */


bool isSameTree(struct TreeNode* p, struct TreeNode* q)
{
    // 都是空树
    if (NULL == p && NULL == q)
    {
        return true;
    }

    // 如果一个为空,一个不为空,返回false
    if (NULL == p || NULL == q)
    {
        return false;
    }

    // 两颗树的每个结点值都相同(或都为空)(两棵树的根和左右子树值都相同),返回true
    if (p->val != q->val) // 仅仅一个结点相同不至于返回true,所以用二者不同来控制
    {
        return false;
    }

    // 说明两树的根值相同,接下来递归比较他们的左右子树
    return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
}

三、力扣101. 对称二叉树

// 101. 对称二叉树


// 第一遍自己写:(一边写,一边画图验证)(同讲)
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
 // 创建子函数
bool _isSymmetric(struct TreeNode* left, struct TreeNode* right)
{
    // 类似于判断两棵树是否相同
    if (NULL == left && NULL == right)
    {
        return true;
    }

    // 一颗为空,一颗不为空
    if (NULL == left || NULL == right)
    {
        return false;
    }

    // 判断每棵树的根节点,左右子树,是否对称
    // 判断根节点是否对称(一个结点比较相同)(如果相同也不至于返回true),所以用二者不同来控制
    if (left->val != right->val)
    {
        return false;
    }

    // 根结点对称下,对比左右子树是否对称
    return _isSymmetric(left->right, right->left) && _isSymmetric(left->left, right->right);

    // 可以合并为:
    /*return left->val == right->val 
         &&_isSymmetric(left->right, right->left) 
         &&_isSymmetric(left->left, right->right);*/
}

bool isSymmetric(struct TreeNode* root)
{
    if (NULL == root)
    {
        return true;
    }

    // 根结点不为空,判断左右子树是否对称
    return _isSymmetric(root->left, root->right);
}

四、力扣144. 二叉树的前序遍历(中,后同理)

// 144. 二叉树的前序遍历(中,后同理)


// 第一遍自己写(看了指点):(一边写,一边画图验证)(同讲)
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */


 /**
  * Note: The returned array must be malloced, assume caller calls free().
  */

int BTreeSize(struct TreeNode* root)
{
    return NULL == root ? 0 : 1 + BTreeSize(root->left) + BTreeSize(root->right);
}

void _preorderTraversal(struct TreeNode* root, int* arr, int* pi) // 指点下才觉得子函数返回值应为空!!!!!!!!
{
    if (NULL == root)
    {
        return; // 如果根结点为空,直接返回
    }

    // 前面已经判断为非空树
    // 先根
    arr[(*pi)++] = root->val;

    // 再左子树
    _preorderTraversal(root->left, arr, pi);

    // 后右子树
    _preorderTraversal(root->right, arr, pi);
}

int* preorderTraversal(struct TreeNode* root, int* returnSize)
{

    // 先要求得二叉树得结点个数,再开辟空间
    int size = BTreeSize(root);
    *returnSize = size;

    // 空树直接返回NULL
    // if(NULL == root) //其实不需要,因为后续代码包括了
    // {
    //     return NULL;
    // }

    // 开辟返回数组空间
    int* arr = (int*)malloc(size * sizeof(int)); // 为了避免每次都创建空间,构建子函数,指点!!!!!!!
    assert(arr);

    // 记录返回数组当前下标
    int i = 0;
    _preorderTraversal(root, arr, &i);// 传入下标地址每次递归避免了无法获取局部变量的问题
    return arr;
}

五、力扣572. 另一棵树的子树

// 572. 另一棵树的子树


// 第一遍自己写:(一边写,一边画图验证)
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */


bool isSameTree(struct TreeNode* p, struct TreeNode* q)
{
    // 都是空树
    if (NULL == p && NULL == q)
    {
        return true;
    }

    // 如果一个为空,一个不为空,返回false
    if (NULL == p || NULL == q)
    {
        return false;
    }

    // 两颗树的每个结点值都相同(或都为空)(两棵树的根和左右子树值都相同),返回true
    if (p->val != q->val) // 仅仅一个结点相同不至于返回true,所以用二者不同来控制
    {
        return false;
    }

    // 说明两树的根值相同,接下来递归比较他们的左右子树
    return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
}

bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot)
{
    // 如果二者均为空
    if (NULL == root && NULL == subRoot)
    {
        return true;
    }

    // 如果二者其中一个为空,另一个不为空
    if (NULL == root || NULL == subRoot)
    {
        return false;
    }

    // 二者均不为空
    // 判断root的每一个结点是否和subRoot相同
    // 所以,先判断root从根结点起和subroot是否相同,接着比较root的子结点
    if (isSameTree(root, subRoot))
    {
        return true;
    }

    // 从root根结点起与subroot比较不同,则递归迭代root的左子树或者右子树是否与subroot相同
    // 遍历子树的每个结点,把它当成子树的根
    // 一旦找到,就返回true,如果在左子树找到则根据逻辑或的短路,右子树无须找,直接返回true
    return isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot);


}





// 讲:
bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot)
{
    if (NULL == root)
    {
        return false; // 其余判空情况可以交给isSametree()
    }

    return isSameTree(root, subRoot)
        || isSubtree(root->left, subRoot)
        || isSubtree(root->right, subRoot);

}

六、牛客KY11 二叉树遍历

// KY11 二叉树遍历


// 自己写:(有问题,没有想到用返回值链接以前的树的问题)

//#include <stdio.h>
//#include <stdlib.h>
//
//
//typedef char BTDataType;
//
//typedef struct BinaryTreeNode
//{
//    BTDataType data;
//    struct BinaryTreeNode* left;
//    struct BinaryTreeNode* right;
//}BTNode;
//
 前序遍历(先根遍历)
//void PreOrder(BTNode* root)
//{
//    if (NULL == root)
//    {
//        return;
//    }
//
//    printf("%d ", root->data);
//    PreOrder(root->left);
//    PreOrder(root->right);
//}
//
 创建二叉树子函数
//void _BTreeCreate(BTNode* root, BTDataType* a, int n, int* pi)
//{
//    if ('\0' == a[*pi])
//    {
//        return;
//    }
//
//    // 先根
//    if ('#' == a[*pi])
//    {
//        // 空结点
//        return;
//        (*pi)++;
//
//        // 先根
//        root->data = a[(*pi)++];
//
//        // 再左子树
//        _BTreeCreate(root->left, a, n, pi);
//        // 再右子树
//        _BTreeCreate(root->right, a, n, pi);
//    }
//}
//
 创建二叉树
//BTNode* BTreeCreate(BTDataType * a, int n, int* pi)
//{
//    // 题目要求:先序遍历顺序来创建链式二叉树
//    BTNode* tmp = (BTNode*)malloc(n * sizeof(BTDataType));
//    if (NULL == tmp)
//    {
//        return;
//    }
//
//    BTNode* tree = tmp;
//
//    _BTreeCreate(tree, a, n, pi);
//
//    return tree;
//}
//
//
 中序遍历
//void InOrder(BTNode * root)
//{
//    if (NULL == root)
//    {
//        return;
//    }
//
//    // 非空结点打印
//    if ((root->left)->data)
//    {
//        // 只打印非空数据
//        printf("%d ", (root->left)->data);
//    }
//
//    InOrder(root);
//    InOrder(root->right);
//}
//
//int main()
//{
//    char str[101] = "";
//    scanf("%s", str);
//    int n = 0;
//    char* tmp = str;
//    while (*tmp++)
//    {
//        n++;
//    }
//
//    // 充当下标
//    int i = 0;
//    BTNode* tree = BTreeCreate(str, n, &i);// 为了使函数中下标的改变可以全局化
//
//    // 中序遍历
//    InOrder(tree);
//
//    return 0;
//}





// 讲后自己写(同讲)
#include <stdio.h>
#include <stdlib.h>


typedef char BTDataType;

typedef struct BinaryTreeNode
{
    BTDataType data;
    struct BinaryTreeNode* left;
    struct BinaryTreeNode* right;
}BTNode;


// 创建二叉树
BTNode* BTreeCreate(BTDataType* a, int* pi)
{
    // 题目要求:先序遍历顺序来创建链式二叉树
    // 每次创建一个结点空间
    BTNode* tmp = (BTNode*)malloc(sizeof(BTDataType));
    if (NULL == tmp)
    {
        return NULL;
    }

    BTNode* root = tmp;

    if ('#' == a[*pi])
    {
        (*pi)++;
        return NULL;
    }

    // 先链接根
    root->data = a[(*pi)++];
    // 再链接左子树
    root->left = BTreeCreate(a, pi);
    // 后链接右子树
    root->right = BTreeCreate(a, pi);

    return root;
}


// 中序遍历
void InOrder(BTNode* root)
{
    if (NULL == root)
    {
        return;
    }

    // 先左子树
    InOrder(root->left);
    // 再根
    printf("%c ", root->data);
    // 后右子树
    InOrder(root->right);
}


int main()
{
    char str[101] = "";
    scanf("%s", str);

    // 充当下标
    int i = 0;
    BTNode* tree = BTreeCreate(str, &i);// 为了使函数中下标的改变可以全局化

    // 中序遍历
    InOrder(tree);

    return 0;
}

总结

这里对文章进行总结:
以上就是今天总结的内容,本文包括了二叉树基础oj题型总结-C语言实现,分享给大家。
真💙欢迎各位给予我更好的建议,欢迎访问!!!小编创作不易,觉得有用可以一键三连哦,感谢大家。peace
希望大家一起坚持学习,共同进步。梦想一旦被付诸行动,就会变得神圣。

欢迎各位大佬批评建议,分享更好的方法!!!🙊🙊🙊

此插件为跨域插件,打开后可跨域访问接口,旧版浏览器可直接拖到扩展程序中安装,新版浏览器需要将扩展名修改成rar并解压,然后点击“加载已解压的扩展程序”安装。 ======================插件概述谷歌译文====================== 轻松将(Access-Control-Allow-Origin:*)规则添加到响应标头。 允许CORS:通过Access-Control-Allow-Origin,您可以轻松地在Web应用程序中执行跨域Ajax请求。 只需激活插件并执行请求。默认情况下(在JavaScript API中),CORS或跨源资源共享在现代浏览器中被阻止。安装此加载项将使您可以解除阻止此功能。请注意,将插件添加到浏览器后,默认情况下它处于非活动状态(工具栏图标为灰色C字母)。如果要激活加载项,请按一次工具栏图标。图标将变为橙色的C字母。 ======================插件概述谷歌译文====================== ========================插件概述原文======================== Easily add (Access-Control-Allow-Origin: *) rule to the response header. Allow CORS: Access-Control-Allow-Origin lets you easily perform cross-domain Ajax requests in web applications. Simply activate the add-on and perform the request. CORS or Cross Origin Resource Sharing is blocked in modern browsers by default (in JavaScript APIs). Installing this add-on will allow you to unblock this feature. Please note that, when the add-on is added to your browser, it is in-active by default (toolbar icon is grey C letter). If you want to activate the add-on, please press on the toolbar icon once. The icon will turn to orange C letter. ========================插件概述原文========================
Access-Control-Allow-OriginCORS(跨域资源共享)中的一个关键字段。它用于确定哪些源(域)可以访问特定的资源。在CORS中,服务器通过在HTTP响应头中设置Access-Control-Allow-Origin字段来指定允许访问该资源的源。 根据引用,Access-Control-Allow-Origin的值是单数,表示只允许一个源进行访问。如果设为Access-Control-Allow-Origins,则表示允许多个源进行访问。 根据引用,可以通过设置HTTP响应头中的Access-Control-Allow-Origin字段来指定允许访问资源的源。例如,可以设置多个Access-Control-Allow-Origin字段,每个字段对应一个允许访问的源。 根据引用,Access-Control-Allow-Origin字段也可以设置为星号(*),表示允许任意跨源请求。这意味着任何源都可以访问该资源。 总结起来,Access-Control-Allow-OriginCORS中用于确定哪些源可以访问特定资源的字段,它可以单独指定一个源,也可以设置多个源,甚至可以设置为星号表示允许任意跨源请求。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Cors跨域(三):Access-Control-Allow-Origin多域名?](https://blog.youkuaiyun.com/f641385712/article/details/117902613)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [Access-Control-Allow- 设置跨域资源共享CORS详解](https://blog.youkuaiyun.com/zhangge3663/article/details/117409636)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值