树低级(C语言版)

一.树基本计算规则

关于树的大部分知识点我们都讲过了,那么如果我给你树的节点,你可以算出叶子节点个数吗?

下面我们总结下一些计算规则:

1.父子计算规则:

parent=(child-1)/2;

leftchild=parent*2+1,rightchild=parent*2+2;

2.若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有2^(i-1)个节点

3.深度为h的二叉树的最大结点数是2^h-1;

4. 对任何一棵二叉树, 如果度为0其叶结点个数为N0 , 度为2的分支结点个数为N2 ,则有

N0=N2+1
5. 若规定根节点的层数为1,具有n个结点的满二叉树的深度,h=log(n+1)  (log以2 为底,n+1为对数)
例题一:
1. 某二叉树共有 399 个结点,其中有 199 个度为 2 的结点,则该二叉树中的叶子结点数为
A 不存在这样的二叉树
B 200
C 198
D 199
规则4,结果为200个,即B
如果不知道规则,那么就可能浪费不必要的时间,大家可以自行去找其他题目。

二.层序遍历

上次我们留下层序遍历没实现,现在我们学习树更近一步了,我们可以实现层序遍历了,在实现前让我们来看看下面两个概念:
深度优先遍历(Depth First Search):简称DFS,前序遍历,中序遍历和后序遍历都是,即一种 递归的遍历方式从一个起点开始,沿着一条路径一直走到底,直到不能再走为止,然后回溯到上一个节点,继续遍历其他路径,直到所有节点都被遍历过。
广度优先遍历(Breadth First Search):又称为广度优先搜索,简称BFS。是一种分层的查找过程,每向前走一步可能访问一批顶点,不像深度优先搜索那样有往回退的情况,因此它不是一个递归的算法。它是一个逐层遍历的过程,层序遍历就是BFS。
大家可能都经历过这样一个过程,就是使用QQ时,会推荐好友的好友,这其实就是一个广度优先遍历的实例。
下面回归我们主题:
如何去写层序遍历呢?
这个时候,是不是可以想到用队列,如果我们将树根放进队列,如果我们出队列,将树根的左右子序列放入,这样一直循环,是不是就可以做到层序遍历。
下面请看代码:
// 层序遍历定义(一:一起遍历)
void LevelOrder(TreeNode* root)
{Queue s1;QueueInit(&s1);//判断是否为空,不空的话,先压进一个if(root)QueuePush(&s1, root);while (!QueueEmpty(&s1)){TreeNode* cur = QueueFront(&s1);QueuePop(&s1);printf("%d ", cur->date);//压入它的左右孩子if(root->left)QueuePush(&s1, root->left);if (root->right)QueuePush(&s1, root->right);}printf("\n");
}

还是以这个树,我们检查一下:
//动态开辟空间定义
TreeNode* BuyTreeNode(int x)
{//开辟树的空间TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode));assert(node);node->date = x;node->left = NULL;node->right = NULL;return node;
}
//建立二叉树定义
TreeNode* CreateTree()
{//开辟树并且对每个进行赋值TreeNode* node1 = BuyTreeNode(1);TreeNode* node2 = BuyTreeNode(2);TreeNode* node3 = BuyTreeNode(3);TreeNode* node4 = BuyTreeNode(4);TreeNode* node5 = BuyTreeNode(5);TreeNode* node6 = BuyTreeNode(6);//确定指向node1->left = node2;node1->right = node4;node2->left = node3;node4->left = node5;node4->right = node6;return node1;
}
int main()
{TreeNode* root = CreateTree();LevelOrder(root);BinaryTreeDestory1(root);root = NULL;return 0;
}

结果:

是不是满足了层序遍历,好了,现在如果我让你将每层的结果,一行打印一层结果,该如何写呢?
// 层序遍历定义(二:逐层遍历)
void LevelOrder2(TreeNode* root)
{Queue s1;QueueInit(&s1);int size = 1;//判断是否为空,不空的话,先压进一个if (root != NULL)QueuePush(&s1, root);while (!QueueEmpty(&s1)){while (size>0){TreeNode* cur = QueueFront(&s1);QueuePop(&s1);printf("%d ", cur->date);//压入它的左右孩子if (cur->left)QueuePush(&s1, cur->left);if (cur->right)QueuePush(&s1, cur->right);size--;}printf("\n");size = QueueSize(&s1);}printf("\n");
}

结果:(还是上面的树)

三.判断二叉树是否是完全二叉树

判断一棵树是不是完全二叉树,我们还是可以利用栈来实现,这里很好理解,就直接展示代码了,里面都有注释。
//判断二叉树是否是完全二叉树
bool BinaryTreeComplete(TreeNode* root)
{Queue s1;QueueInit(&s1);//判断是否为空,不空的话,先压进一个if (root != NULL)QueuePush(&s1, root);//找到第一个空while (!QueueEmpty(&s1)){TreeNode* cur = QueueFront(&s1);QueuePop(&s1);if (cur == NULL)break;//压入它的左右孩子,注意:不用判断了		QueuePush(&s1, cur->left);QueuePush(&s1, cur->right);		}//第二步:如果在栈中还有非空,就说明不是完全二叉树//定理:如果不是完全二叉树,那么栈里面此时一定有数据了while (!QueueEmpty(&s1)){TreeNode* cur2 = QueueFront(&s1);QueuePop(&s1);if (cur2 != NULL)return false;}return true;
}

检查:

//建立二叉树定义
TreeNode* CreateTree()
{//开辟树并且对每个进行赋值TreeNode* node1 = BuyTreeNode(1);TreeNode* node2 = BuyTreeNode(2);TreeNode* node3 = BuyTreeNode(3);TreeNode* node4 = BuyTreeNode(4);TreeNode* node5 = BuyTreeNode(5);TreeNode* node6 = BuyTreeNode(6);TreeNode* node7 = BuyTreeNode(7);//确定指向node1->left = node2;node1->right = node4;node2->left = node3;node2->right = node7;node4->left = node5;//node3->left = node5;node4->right = node6;return node1;
}

对于这棵树结果为:
当然,你也可以自己去检查我的结果
对于树的中等部分就补充到这里了,后面我们还会讲一些高级的树,元旦快乐,bye!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/329293.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

听GPT 讲Rust源代码--compiler(32)

File: rust/compiler/rustc_middle/src/middle/exported_symbols.rs 在Rust的源代码中,rust/compiler/rustc_middle/src/middle/exported_symbols.rs文件的作用是实现编译器中处理导出符号的功能。 该文件中定义了一些结构体和枚举,用于描述导出符号的信…

[Android]RadioButton控件

RadioButton控件 RadioButton控件是单选按钮控件,它继承自Button控件,可以直接使用Button控件支持的各种属性和方法。 与普通按钮不同的是,RadioButton控件多了一个可以选中的功能,能额外指定一个android:checked属性…

python中的异常处理

目录 一:处理机制 二:实例 一:处理机制 Python中的异常处理主要通过try/except语句实现。try语句块包含可能会引发异常的代码,而except语句块包含在try块中发生异常时要执行的代码。此外,Python还提供了一个finally语…

维也纳整流电路笔记

不加前馈控制的波形: 加入前馈控制波形: 驱动波形中出现超宽脉冲波形: 仔细分析发现是原始驱动波形产生的。 移相180度后的波形,仍然存在此问题:

次梯度算法介绍

系列文章目录 最优化笔记,主要参考资料为《最优化:建模、算法与理论》 文章目录 系列文章目录一、次梯度1 定义2 存在性 二、次梯度的计算1 按定义计算2 常用计算规则 三、最优性条件1 无约束优化问题2 约束优化问题 四、次梯度算法1 迭代格式2 收敛性 参…

大数据技术架构

1 技术架构矩阵 大数据技术栈虽然比较多,但可以抽象为输入(数据接入)--处理(数据处理、数据分析)--输出(数据应用)。工作角色分工,数据处理以数据仓库开发人员为主,数据分析以数据分析师为主,其他所有组件、系统、技术相关归为数据平台。 2 数据源 大数据的数据来源…

线性规划基本原理与案例分析

线性规划(Linear Programming 简记LP)则是数学规划的一个重要分支。 什么叫做线性规划?一般来讲,目标函数和约束函数均是线性的叫做线性规划问题。线性规划必须满足以下三种基本性质 例1.1 某机床厂生产甲、乙两种机床,每台销售后的利润分别…

关键字:package关键字

在 Java 中,package关键字用于组织和管理类文件。它将类文件分组到不同的包中,以提供更好的代码组织和可读性。 以下是package关键字的用法: 1.package语句:在 Java 源代码的开头使用package关键字来声明当前类所属的包。例如&a…

Python从入门到网络爬虫(异常处理详解)

前言 异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行。一般情况下,在python无法正常处理程序时就会发生一个异常。异常是python对象,表示一个错误。当python脚本发生异常时我们需要捕获处理它,…

【刷题日记】青少年CTF-Misc(一)

靶场链接 青少年CTF Markdown 题目难度:★ 题目描述:s0ng师傅发现M0x1n师傅特别喜欢用这个写文档,你知道M0x1n这次把FLAG放到哪里了吗?flag格式为:qsnctf{xxx}。 下载附件,打开即可看到flag flag qsnc…

大学物理实验重点——霍尔效应

霍尔系数 霍尔元件灵敏度,愈大愈好 负效应: 1. 不等位电势 V0:两个霍尔电极不可能绝对对 称地焊在霍尔元件两侧(图 2)、霍尔元件电阻率不均匀、工作电极的端面接触不良都 可能造成 C、D 两极不处在同一等位面上。R0 确…

Video classification with UniFormer基于统一分类器的视频分类

本文主要介绍了UniFormer: Unified Transformer for Efficient Spatial-Temporal Representation Learning 代码:https://github.com/Sense-X/UniFormer/tree/main/video_classification UNIFormer 动机 由于视频具有大量的局部冗余和复杂的全局依赖关系&#xf…