【C语言 - 数据结构】树、二叉树(下篇)(下)

简介: 【C语言 - 数据结构】树、二叉树(下篇)

3.3怎么求第k层节点的个数?


核心思路:递归返回第k-1层左右结点相加的值

1669440614564.jpg

int BTreekLeafSize(BTNode* root, int k)
{
       assert(k >= 1);
       if (root == NULL) return 0;
       if (k == 1) return 1;
       return BTreekLeafSize(root->left, k - 1) + BTreekLeafSize(root->right, k - 1);//返回左结点和右结点的上一层
}

3.4求一棵树的高度


思想:比较左右子树的高度,并且返回高度大的加一(原因:加根结点)

int BTreeDepth(BTNode* root)
{
       if (root == NULL)
              return 0;
       int leftDepth = BTreeDepth(root->left);
       int rightDepth = BTreeDepth(root->right);
       return leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1;
}


3.5二叉树查找值为x的结点


1669440667333.jpg

思路:用前序遍历去递归搜索,先搜左子树,如果左子树没有,就返回一个NULL到根结点,然后根结点再递归搜索右树,如果右树有就返回那个点的值。

BTNode* BTreeFind(BTNode* root, BTDataType x)
{
       if (root == NULL)
              return NULL;
       if (root->data == x)
              return root;
       //用前序遍历的思想
       BTNode* ret1 = BTreeFind(root->left, x);//先去递归左树
       if (ret1)//如果左边返回的不是NULL
       {
              return ret1;
       }
       BTNode* ret2 = BTreeFind(root->right, x);
       if (ret2)
       {
              return ret2;
       }
       return NULL;
}


3.6判断一棵树是不是完全二叉树


思路:就是把空也当作二叉树的节点放进去,然后运用层序遍历,


如果在遍历的中间过程中遇到空就说明不是完全二叉树。


队列不能直接像数组一样遍历


1669440692995.jpg


//判断一棵树是不是完全二叉树
bool BinaryTreeComplete(BTNode* root)
{
       Queue q;
       QueueInit(&q);
       if (root)
       {
              QueuePush(&q, root);//先插入根节点
       }
       while (!QueueEmpty(&q))
       {
              BTNode* front = QueueFront(&q);//会等于队头第一个数据的值
              QueuePop(&q);
              if (front == NULL)
              {
                      break;
              }
              QueuePush(&q, front->left);
              QueuePush(&q, front->right);
       }
       while (!QueueEmpty(&q))
       {
              BTNode* front = QueueFront(&q);//会等于队头第一个数据的值
              QueuePop(&q);
              if (front)//如果出到非空,那么就不是完全二叉树
              {
                      return false;
              }
       }
       return true;
}


四、二叉树oj题


1、965. 单值二叉树 - 力扣(LeetCode)


1669440742029.jpg

bool isUnivalTree(struct TreeNode* root)
{
    if(root == NULL) return true;
    if(root->left && root->left->val != root->val)//如果左结点不为空,且左树结点的值不等于根的值,返回false
         return false;
    if(root->right && root->right->val != root->val)//如果右结点不为空,且右树结点的值不等于根的值,返回false
        return false;
    return isUnivalTree(root->left) && isUnivalTree(root->right);//递归判断
}

2、100. 相同的树 - 力扣(LeetCode)


1669440767996.jpg


思路:先判断两棵树是不是都是空树,再判断如果一个为空一个不为空,最后递归

bool isSameTree(struct TreeNode* p, struct TreeNode* q)
{
    //判断两个树的根是不是都为空
    if(p == NULL && q == NULL)
        return true;
    //判断两个树的其中一颗树的结点为空时,另一个不为空
    if(p == NULL || q == NULL)
        return false;
    //判断两个树的根节点是否是同值
    if(p->val != q->val)
        return false;
        //递归判断
    return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
}

注意:这里的判断不能写成p->left->val != q->left->val

会报错


3、101. 对称二叉树 - 力扣(LeetCode)


1669440796631.jpg


思路:写一个辅助函数,舍弃根结点,判断左边这个树是否与右边这个树对称

bool isSymmetricTree(struct TreeNode* p, struct TreeNode* q)
{
    //如果root的左和右节点都为空
    if(p == NULL && q == NULL) 
    return true;
    //如果一个为空一个不为空
    if(p == NULL || q == NULL) 
    return false;
    return p->val == q->val 
    && isSymmetricTree(p->left, q->right)
    && isSymmetricTree(p->right, q->left);
}
bool isSymmetric(struct TreeNode* root)
{
    if(root == NULL) 
    return true;
    return isSymmetricTree(root->left, root->right);
}


4、144. 二叉树的前序遍历 - 力扣(LeetCode)


1669440823695.jpg


题目意思解释:Note: The returned array must be malloced, assume caller calls free().


这句话的意思是数组要malloc, 然后caller系统会帮你free掉


int* returnSize的意思是返回结点的个数


代码如下所示:

int TreeSize(struct TreeNode* root)//计算树的结点个数,方便malloc空间
{
    return root == NULL ? 0 : TreeSize(root->left) + 
    TreeSize(root->right) + 1;
}
//定义一个子函数去完成前序遍历
void _preorder(struct TreeNode* root, int* a,int *pi)
{
    if(root == NULL)
      return;
    a[(*pi) ++] = root->val;//控一下优先级*的优先级低于++,所以要加()
    _preorder(root->left, a, pi);
    _preorder(root->right, a, pi);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize)//int*returnSize是输出型参数
{
    int size = TreeSize(root);
    //不考虑动态扩容
    int* a = malloc(sizeof(int)*size);
    int i = 0;
    *returnSize = size;
    _preorder(root, a, &i);
    return a;
}

因为之后的二叉树中序以及后序遍历思路差不多,所以如果读者有兴趣可以根据这个思路去做。


5、572. 另一棵树的子树 - 力扣(LeetCode)


1669440849422.jpg


思路:左边树中每一个子树都比较isSameTree


遍历左边的每个节点,做子树的根,跟右边的子树都比较一下isSameTree


bool isSameTree(struct TreeNode* p, struct TreeNode* q)
{
    //两棵树的根都为空
    if (p == NULL && q == NULL)
        return true;
    //只有一颗树为空 此时已经有同位置的节点不相等
    if(p == NULL || q == NULL)
        return false;
    if(p->val != q->val)
    return false;
    return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
}
bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot)
{
    if(root == NULL)
        return;
    if(isSameTree(root, subRoot))
    {
        return true;
    }
    return isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot);
}


6.二叉树遍历_牛客题霸_牛客网 (nowcoder.com)


先序遍历字符串构造的二叉树(前序)


递归、分治的思想

1669440882489.jpg

1669440896236.jpg

#include<stdio.h>
#include<string.h>
//构造结构体
typedef struct BinaryTreeNode
{
    char data;
    struct BinaryTreeNode* left;
    struct BinaryTreeNode* right;
}BTNode;
//造树
BTNode* CreatTree(char* a, int* pi)
{
    if(a[*pi] == '#')
    {
        (*pi)++;
        return NULL;
    }
    BTNode* root = (BTNode*)malloc(sizeof(BTNode));
    root->data = a[(*pi)++];
    root->left = CreatTree(a, pi);
    root->right = CreatTree(a, pi);
    return root;
}
void InOrder(BTNode* root)
{
    if(root == NULL)//这里root直接等于NULL判断便可,不需要‘#
    {
        return;
    }
    InOrder(root->left);
    printf("%c ", root->data);
    InOrder(root->right);
}
//main函数部分
int main ()
{
    char a[101];
    scanf("%s", a);
    int i = 0;
    BTNode* tree = CreatTree(a, &i);
    InOrder(tree);
    return 0;
}
相关文章
|
5月前
|
存储 C语言
c语言——二叉树
二叉树的概念在这里就不进行过多的赘述,那么主要说一下我认为重要的部分,第一点就是二叉树里面部分概念的理解:就比如说,你对于如何构建二叉树,掌握的十分深刻,但刷题的时候对于一些题目所给的概念不清楚,导致看不明白题目,这课不好,二叉树的概念如下图所示,其实都很简单,主要是当给他的名字时,你明不明白。还有对于满二叉树与完全二叉树。
109 0
|
8月前
|
存储 算法 Java
算法系列之数据结构-二叉树
树是一种重要的非线性数据结构,广泛应用于各种算法和应用中。本文介绍了树的基本概念、常见类型(如二叉树、满二叉树、完全二叉树、平衡二叉树、B树等)及其在Java中的实现。通过递归方法实现了二叉树的前序、中序、后序和层次遍历,并展示了具体的代码示例和运行结果。掌握树结构有助于提高编程能力,优化算法设计。
256 10
 算法系列之数据结构-二叉树
|
8月前
|
算法 Java
算法系列之数据结构-Huffman树
Huffman树(哈夫曼树)又称最优二叉树,是一种带权路径长度最短的二叉树,常用于信息传输、数据压缩等方面。它的构造基于字符出现的频率,通过将频率较低的字符组合在一起,最终形成一棵树。在Huffman树中,每个叶节点代表一个字符,而每个字符的编码则是从根节点到叶节点的路径所对应的二进制序列。
206 3
 算法系列之数据结构-Huffman树
|
8月前
|
存储 自然语言处理 数据库
【数据结构进阶】AVL树深度剖析 + 实现(附源码)
在深入探讨了AVL树的原理和实现后,我们不难发现,这种数据结构不仅优雅地解决了传统二叉搜索树可能面临的性能退化问题,还通过其独特的平衡机制,确保了在任何情况下都能提供稳定且高效的查找、插入和删除操作。
635 19
|
10月前
|
存储 C++
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
【数据结构——树】哈夫曼树(头歌实践教学平台习题)【合集】目录 任务描述 相关知识 测试说明 我的通关代码: 测试结果:任务描述 本关任务:编写一个程序构建哈夫曼树和生成哈夫曼编码。 相关知识 为了完成本关任务,你需要掌握: 1.如何构建哈夫曼树, 2.如何生成哈夫曼编码。 测试说明 平台会对你编写的代码进行测试: 测试输入: 1192677541518462450242195190181174157138124123 (用户分别输入所列单词的频度) 预
328 14
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
|
9月前
|
定位技术 C语言
c语言及数据结构实现简单贪吃蛇小游戏
c语言及数据结构实现简单贪吃蛇小游戏
|
10月前
|
搜索推荐 C语言
数据结构(C语言)之对归并排序的介绍与理解
归并排序是一种基于分治策略的排序算法,通过递归将数组不断分割为子数组,直到每个子数组仅剩一个元素,再逐步合并这些有序的子数组以得到最终的有序数组。递归版本中,每次分割区间为[left, mid]和[mid+1, right],确保每两个区间内数据有序后进行合并。非递归版本则通过逐步增加gap值(初始为1),先对单个元素排序,再逐步扩大到更大的区间进行合并,直至整个数组有序。归并排序的时间复杂度为O(n*logn),空间复杂度为O(n),且具有稳定性,适用于普通排序及大文件排序场景。
|
10月前
|
Java C++
【C++数据结构——树】二叉树的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现二叉树的基本运算。​ 相关知识 创建二叉树 销毁二叉树 查找结点 求二叉树的高度 输出二叉树 //二叉树节点结构体定义 structTreeNode{ intval; TreeNode*left; TreeNode*right; TreeNode(intx):val(x),left(NULL),right(NULL){} }; 创建二叉树 //创建二叉树函数(简单示例,手动构建) TreeNode*create
276 12
|
10月前
|
C++
【C++数据结构——树】二叉树的性质(头歌实践教学平台习题)【合集】
本文档介绍了如何根据二叉树的括号表示串创建二叉树,并计算其结点个数、叶子结点个数、某结点的层次和二叉树的宽度。主要内容包括: 1. **定义二叉树节点结构体**:定义了包含节点值、左子节点指针和右子节点指针的结构体。 2. **实现构建二叉树的函数**:通过解析括号表示串,递归地构建二叉树的各个节点及其子树。 3. **使用示例**:展示了如何调用 `buildTree` 函数构建二叉树并进行简单验证。 4. **计算二叉树属性**: - 计算二叉树节点个数。 - 计算二叉树叶子节点个数。 - 计算某节点的层次。 - 计算二叉树的宽度。 最后,提供了测试说明及通关代
188 10
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
270 59

热门文章

最新文章