数据结构第六课 -----链式二叉树的实现

作者前言

🎂 ✨✨✨✨✨✨🍧🍧🍧🍧🍧🍧🍧🎂
​🎂 作者介绍: 🎂🎂
🎂 🎉🎉🎉🎉🎉🎉🎉 🎂
🎂作者id:老秦包你会, 🎂
简单介绍:🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂
喜欢学习C语言和python等编程语言,是一位爱分享的博主,有兴趣的小可爱可以来互讨 🎂🎂🎂🎂🎂🎂🎂🎂
🎂个人主页::小小页面🎂
🎂gitee页面:秦大大🎂
🎂🎂🎂🎂🎂🎂🎂🎂
🎂 一个爱分享的小博主 欢迎小可爱们前来借鉴🎂


链式二叉树

  • **作者前言**
  • 二叉树
  • 二叉树的遍历
    • 前序遍历
    • 中序遍历
    • 后序遍历
  • 小例子
  • 知识点

二叉树

前面粗略的介绍了二叉树
二叉树主要有两种 空树和非空树
而非空树拆分为 : 根节点 和左子树和右子树
在这里插入图片描述
二叉树的性质

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

  2. 若规定根节点的层数为1,则深度为h的二叉树的最大结点数是2^h -1 .

  3. 对任何一棵二叉树, 如果度为0其叶结点个数为n0 , 度为2的分支结点个数为n2 ,则有 n0= n2+1

  4. 若规定根节点的层数为1,具有n个结点的满二叉树的深度,h=log(n+1) . (ps: 是log以2
    为底,n+1为对数)

  5. 对于具有n个结点的完全二叉树,如果按照从上至下从左至右的数组顺序对所有节点从0开始编号,则对于序号为i的结点有:

    1. 若i>0,i位置节点的双亲序号:(i-1)/2;i=0,i为根节点编号,无双亲节点
    2. 若2i+1<n,左孩子序号:2i+1,2i+1>=n否则无左孩子
    3. 若2i+2<n,右孩子序号:2i+2,2i+2>=n否则无右孩子

二叉树的遍历

学习二叉树结构,最简单的方式就是遍历。所谓二叉树遍历(Traversal)是按照某种特定的规则,依次对二叉树中的节点进行相应的操作,并且每个节点只操作一次。访问结点所做的操作依赖于具体的应用问题。 遍历是二叉树上最重要的运算之一,也是二叉树上进行其它运算的基础。

按照规则,二叉树的遍历有:前序/中序/后序的递归结构遍历:

  1. 前序遍历(Preorder Traversal 亦称先序遍历)——访问根结点的操作发生在遍历其左右子树之前。(根 ->左 ->右)

  2. 中序遍历(Inorder Traversal)——访问根结点的操作发生在遍历其左右子树之中(间)。(左->根->右)

  3. 后序遍历(Postorder Traversal)——访问根结点的操作发生在遍历其左右子树之后。(左->右->根)

为此特意构建一个二叉树

#include<stdio.h>
#include<stdlib.h>
typedef int BTDataType;
typedef struct BinaryTreeNode
{BTDataType* val;struct BinaryTreeNode* left;struct BinaryTreeNode* rigth;}BinaryTreeNode;
BinaryTreeNode* CreateNode(BTDataType elemest)
{BinaryTreeNode* p = (BinaryTreeNode*)malloc(sizeof(BinaryTreeNode));if (p == NULL){perror("malloc");return -1;}p->val = elemest;return p;
}
int main()
{BinaryTreeNode* n1 = CreateNode(1);BinaryTreeNode* n2 = CreateNode(2);BinaryTreeNode* n3 = CreateNode(3);BinaryTreeNode* n4 = CreateNode(4);BinaryTreeNode* n5 = CreateNode(5);BinaryTreeNode* n6 = CreateNode(6);n1->left = n2;n1->rigth = n4;n2->left = n3;n2->rigth = NULL;n3->left = NULL;n3->rigth = NULL;n4->left = n5;n4->rigth = n6;n5->left = NULL;n5->rigth = NULL;n6->left = NULL;n6->rigth = NULL;return 0;
}

前序遍历

我们以上面图片为例
我们可以写成:
1 2 3 N N N 4 5 N N 6 N N
代码:

void PreOrder(BinaryTreeNode* n1)
{if (n1 == NULL){printf("NULL ");return;}printf("%d ", n1->val);PreOrder(n1->left);PreOrder(n1->rigth);
}

在这里插入图片描述

中序遍历

我们可以写成:N 3 N 2 N 1 N 5 N 4 N 6 N
代码:

void InOrdef(BinaryTreeNode* n1)
{if (n1 == NULL){printf("NULL ");return;}PreOrder(n1->left);printf("%d ", n1->val);PreOrder(n1->rigth);
}

后序遍历

我们可以写成: N N 3 N 2 N N 5 N N 6 4 1
代码:

void PostOrder(BinaryTreeNode* n1)
{if (n1 == NULL){printf("NULL ");return;}PreOrder(n1->left);PreOrder(n1->rigth);printf("%d ", n1->val);
}

小例子

叶子节点个数
思路:左子树的节点个数加上右子树的节点个数加上根节点

//节点个数
int TreeSize(BinaryTreeNode* n1)
{if (n1 == NULL)return 0;return 1 + TreeSize(n1->left) + TreeSize(n1->rigth);
}

叶节点个数
思路:左子树的叶节点个数加上右子树的叶节点个数加上根节点 需要注意的是为空树.和只有根节点的情况

//叶节点的个数
int TreeLeafSize(BinaryTreeNode* n1)
{//为空树if (n1 == NULL)return 0;//只有一个节点if (n1->left == NULL && n1->rigth == NULL)return 1;return TreeLeafSize(n1->left) + TreeLeafSize(n1->rigth);
}

树的高度
思路:左子树的高度和右子树高度比较,大的高度加上1就是整个二叉树的高度,需要注意的是空树情况下

int TreeHeigth(BinaryTreeNode* n1)
{if (n1 == NULL)return 0;if (n1->left == NULL && n1->rigth == NULL)return 1;int a = TreeHeigth(n1->left);int b = TreeHeigth(n1->rigth);return (a > b ? a : b) + 1;
}

#第k层的节点
思路: 左子树的第k-1层的节点个数 加上右子树的第k-1层的节点个数,如果k为0就是空,k=1,就是1

int NodeNum(BinaryTreeNode* n1, int k)
{if (n1 == NULL)return 0;if (k == 0)return 0;if (k == 1)return 1;return NodeNum(n1->left, k - 1) + NodeNum(n1->rigth, k - 1);
}

层次遍历
思路:层次遍历就是从第一层开始横向遍历
我们可以借助队列的性质,先进先出,我们先开始插入根节点,然后开始进行循环判断,只要出去的节点的左右孩子不为NULL就插入到队列,直到队列为空
在这里插入图片描述

// 层序遍历
void BinaryTreeLevelOrder(BinaryTreeNode* root)
{//创建一个队列Queue Qu;//初始化QueueInit(&Qu);//插入的是节点,if (root != NULL)QueuePush(&Qu, root);while (QueueSize(&Qu)){BinaryTreeNode* from = QueueFront(&Qu);printf("%d ", from->val);//删除QueuePop(&Qu);//需要注意的是删除只是释放掉存储了二叉树节点的地址的空间,并没有释放二叉树节点if (from->left != NULL){QueuePush(&Qu, from->left);}if (from->rigth != NULL){QueuePush(&Qu, from->rigth);}}printf("\n");QueueDestroy(&Qu);}

这个是打印全部的
如果要一层层的打印
思路: 我们可以定义一个变量,用来统计当前队列的个数,也就是当层的节点个数,然后每出列一个就把对应的左右孩子插入进去,然后该变量减1,直到为0,也就是该层的节点全部出列了,然后再计算出队列的长度,也就是下一层的节点个数,然后继续,直到队列的长度为0

在这里插入图片描述

// 层序遍历
void BinaryTreeLevelOrder(BinaryTreeNode* root)
{//创建一个队列Queue Qu;//初始化QueueInit(&Qu);//插入的是节点,if (root != NULL)QueuePush(&Qu, root);int size = QueueSize(&Qu);while (QueueSize(&Qu)){while (size--){BinaryTreeNode* from = QueueFront(&Qu);printf("%d ", from->val);//删除QueuePop(&Qu);//需要注意的是删除只是释放掉存储了二叉树节点的地址的空间,并没有释放二叉树节点if (from->left != NULL){QueuePush(&Qu, from->left);}if (from->rigth != NULL){QueuePush(&Qu, from->rigth);}}printf("\n");size = QueueSize(&Qu);}printf("\n");QueueDestroy(&Qu);}

判断是否是完全二叉树
思路:我们和上面的层次遍历一样,先找一个队列进行一层层的入队和出队,如果遇见节点为NULL的就判断后面是否还有节点存在

// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BinaryTreeNode* root)
{//创建一个队列Queue Qu;//初始化QueueInit(&Qu);//插入的是节点,if (root != NULL)QueuePush(&Qu, root);while (QueueSize(&Qu)){BinaryTreeNode* from = QueueFront(&Qu);if (from == NULL)break;//删除QueuePop(&Qu);//需要注意的是删除只是释放掉存储了二叉树节点的地址的空间,并没有释放二叉树节点QueuePush(&Qu, from->left);QueuePush(&Qu, from->rigth);}//判断后面是否还有非空while (!QueueEmtry(&Qu)){BinaryTreeNode* from = QueueFront(&Qu);if (from != NULL)return 0;//删除QueuePop(&Qu);}QueueDestroy(&Qu);return 1;}

知识点

前序:深度优先遍历
层序: 广度优先遍历

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

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

相关文章

centos7 设置静态ip

文章目录 设置VMware主机设置centos7 设置 设置VMware 主机设置 centos7 设置 vim /etc/sysconfig/network-scripts/ifcfg-ens33重启网络服务 service network restart检验配置是否成功 ifconfig ip addr

filter过滤器

package com.it.filter;import javax.servlet.*; import javax.servlet.annotation.WebFilter;import java.io.IOException;WebFilter(urlPatterns"/*") public class DemoFilter implements Filter {Override // 初始化的方法 只要调用一次public void init(Filte…

什么是深度「穿透式」供应链?苹果多层级穿透式供应链分析|徐礼昭

徐礼昭&#xff08;商派市场负责人&#xff0c;重构零售实验室负责人&#xff09; 什么是「穿透式供应链」&#xff1f; 穿透式供应链是一种新型的供应链体系&#xff0c;它强调纵深拓展和动态优化&#xff0c;以满足供应链的安全需求和价值需求。这种供应链体系由多个层级组成…

深圳市左下右上百度坐标

爬取百度POI的时候&#xff0c;别人的代码中有提到左下&#xff0c;右上坐标&#xff0c;但是没有说从哪里来&#xff0c;而且还是百度的坐标。 经纬度:左下角,右上角&#xff1a;113.529103,37.444122;115.486183,38.768031 墨卡托坐标:左下角,右上角&#xff1a;12638139.45,…

Python中的类(Class)和对象(Object)

目录 一、引言 二、类&#xff08;Class&#xff09; 1、类的定义 2、类的实例化 三、对象&#xff08;Object&#xff09; 1、对象的属性 2、对象的方法 四、类和对象的继承和多态性 1、继承 2、多态性 五、类与对象的封装性 1、封装的概念 2、Python中的封装实现…

个人博客搭建保姆级教程-HTML页面编写篇

选择模板 首先我们要选一个好的模板&#xff0c;然后对模板进行剪裁。我的模板是在站长之家进行下载的 素材下载-分享综合设计素材免费下载的平台-站长素材 我选的模板的具体地址是 个人博客资讯网页模板 这里需要我们学习一下在前边一篇文章里提到的HTML、JavaScript、CSS…

Learning Normal Dynamics in Videos with Meta Prototype Network 论文阅读

文章信息&#xff1a;发表在cvpr2021 原文链接&#xff1a; Learning Normal Dynamics in Videos with Meta Prototype Network 摘要1.介绍2.相关工作3.方法3.1. Dynamic Prototype Unit3.2. 视频异常检测的目标函数3.3. 少样本视频异常检测中的元学习 4.实验5.总结代码复现&a…

Python自动化测试selenium指定截图文件名方法

这篇文章主要介绍了Python自动化测试selenium指定截图文件名方法&#xff0c;Selenium 支持 Web 浏览器的自动化&#xff0c;它提供一套测试函数&#xff0c;用于支持 Web 自动化测试&#xff0c;下文基于python实现指定截图文件名方法&#xff0c;需要的小伙伴可以参考一下 前…

共线圆检查

dev_update_off () dev_close_window () dev_open_window (0, 0, 978, 324, black, WindowHandle) dev_set_part (0, 0, 647, 1955) set_display_font (WindowHandle, 16, mono, true, false) dev_set_color (yellow) *检测图中有多少个圈 *dev_set_line_width (3) read_image…

Python Opencv实践 - Yolov3目标检测

本文使用CPU来做运算&#xff0c;未使用GPU。练习项目&#xff0c;参考了网上部分资料。 如果要用TensorFlow做检测&#xff0c;可以参考这里 使用GPU运行基于pytorch的yolov3代码的准备工作_little han的博客-CSDN博客文章浏览阅读943次。记录一下自己刚拿到带独显的电脑&a…

金融帝国实验室(Capitalism Lab)V10版本公司财务报告列示优化

金融帝国实验室&#xff08;Capitalism Lab&#xff09;V10版本公司财务报告列示优化 ————————————— ★【全新V10版本开发播报】★ 即将发布的V10版本中的公司财务报告&#xff08;指标&#xff09;列示优化&#xff1a; ◈ 新增了一个按钮&#xff0c;用于在历史…

Android启动系列之进程杀手--lmkd

本文概要 这是Android系统启动的第三篇文章&#xff0c;本文以自述的方式来讲解lmkd进程&#xff0c;通过本文您将了解到lmkd进程在安卓系统中存在的意义&#xff0c;以及它是如何杀进程的。&#xff08;文中的代码是基于android13&#xff09; 我是谁 init&#xff1a;“大…

【shell】

shell 一、shell简介二、shell脚本的执行方式三、shell变量3.1 shell变量介绍3.2 shell变量的定义3.1.1 基本语法3.2.2 定义变量的规则3.2.3 将命令的返回值赋予变量 四、环境变量的设置4.1 基本语法&#xff1a; 五、位置参数变量5.1 基本介绍5.2 基本语法 六、预定义变量6.1 …

nginx的反向代理和负载均衡

nginx的反向代理和负载均衡&#xff1a; 代理&#xff1a;客户端通过一个指定的服务器&#xff0c;访问其他服务器&#xff0c;请求和响应都由指定服务器来为客户端进行处理&#xff0c;这个指定的服务器就是代理服务器 代理的方式&#xff1a; 四层代理&#xff1a;四层就是…

操作系统概述及发展史、Linux内核、发行版及应用领域

一、 操作系统&#xff08;Operation System&#xff0c;OS&#xff09; 裸机&#xff1a;没有安装操作系统的计算机 如果想在 裸机 上运行自己所编写的程序&#xff0c;就必须用机器语言书写程序如果计算机上安装了操作系统&#xff0c;就可以在操作系统上安装支持的高级语言…

python pyaudio实时读取音频数据并展示波形图

python pyaudio实时读取音频数据并展示波形图 下面代码可以驱动电脑接受声音数据&#xff0c;并实时展示音波图&#xff1a; import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation import pyaudio import wave import os import op…

面试官:说说synchronized与ReentrantLock的区别

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一波电子书籍资料&#xff0c;包含《Effective Java中文版 第2版》《深入JAVA虚拟机》&#xff0c;《重构改善既有代码设计》&#xff0c;《MySQL高性能-第3版》&…

质量小议35 -- SQL注入

已经记不得上次用到SQL注入是什么时候了&#xff0c;一些概念和操作已经模糊。 最近与人聊起SQL注入&#xff0c;重新翻阅&#xff0c;暂记于此。 重点&#xff1a;敏感信息、权限过大、未脱敏的输入/输出、协议、框架、数据包、明文、安全意识 SQL - Structured Query La…

力扣124. 二叉树中的最大路径和(java DFS解法)

Problem: 124. 二叉树中的最大路径和 文章目录 题目描述思路解题方法复杂度Code 题目描述 二叉树中的 路径 被定义为一条节点序列&#xff0c;序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点&#xff0c;且不一定经…

【C++】类和对象——const修饰成员函数和取地址操作符重载

在上篇博客中&#xff0c;我们已经对于日期类有了较为全面的实现&#xff0c;但是&#xff0c;还有一个问题&#xff0c;比如说&#xff0c;我给一个const修饰的日期类的对象 这个对象是不能调用我们上篇博客写的函数的&#xff0c;因为&d1是const Date*类型的&#xff…