数据结构-二叉树_堆

数据结构-二叉树_堆

目录

1.二叉树的概念

​编辑1.1树的概念与结构

1.2树的相关语

1.3 树的表示

2. ⼆叉树

2.1 概念与结构

2.2 特殊的⼆叉树

2.2.2 完全⼆叉树

2.3 ⼆叉树存储结构

2.3.1 顺序结构

2.3.2 链式结构

3. 实现顺序结构⼆叉树

3.2 堆的实现

 3.2.2 向下调整算法


1.二叉树的概念

1.1树的概念与结构

二叉树和上面的图片一样,有一个根,然后生出两个枝,一个枝又长出两个枝,并且每个枝最多长出两个枝。

  • 有一个特殊的节点,叫做根节点,他没有前驱节点
  • 除根结点外,其余结点被分成 M(M>0) 个互不相交的集合 T1、T2、……、Tm ,其中每⼀个集合 Ti(1 <= i <= m) ⼜是⼀棵结构与树类似的⼦树。每棵⼦树的根结点有且只有⼀个前驱,可以 有 0 个或多个后继。因此,树是递归定义的。

子树之间是不能有交集的

1.2树的相关语

  • ⽗结点/双亲结点:若⼀个结点含有⼦结点,则这个结点称为其⼦结点的⽗结点; 如上图:A是B的⽗ 结点
  • ⼦结点/孩⼦结点:⼀个结点含有的⼦树的根结点称为该结点的⼦结点; 如上图:B是A的孩⼦结点
  • 结点的度:⼀个结点有⼏个孩⼦,他的度就是多少;⽐如A的度为6,F的度为2,K的度为0 树的度:⼀棵树中,最⼤的结点的度称为树的度; 如上图:树的度为 6
  • 叶⼦结点/终端结点:度为 0 的结点称为叶结点; 如上图: B、C、H、I... 等结点为叶结点 分⽀结点/⾮终端结点:度不为 0 的结点; 如上图: D、E、F、G... 等结点为分⽀结点
  • 兄弟结点:具有相同⽗结点的结点互称为兄弟结点(亲兄弟); 如上图: B、C 是兄弟结点 比特就业课
  • 结点的层次:从根开始定义起,根为第 1 层,根的⼦结点为第 2 层,以此类推;
  • 树的⾼度或深度:树中结点的最⼤层次; 如上图:树的⾼度为 4
  • 结点的祖先:从根到该结点所经分⽀上的所有结点;如上图: A 是所有结点的祖先
  • 路径:⼀条从树中任意节点出发,沿⽗节点-⼦节点连接,达到任意节点的序列;⽐如A到Q的路径为: A-E-J-Q;H到Q的路径H-D-A-E-J-Q
  • ⼦孙:以某结点为根的⼦树中任⼀结点都称为该结点的⼦孙。如上图:所有结点都是A的⼦孙
  • 森林:由 m(m>0) 棵互不相交的树的集合称为森林;

1.3 树的表示

孩⼦兄弟表⽰法: 树结构相对线性表就⽐较复杂了,要存储表⽰起来就⽐较⿇烦了,既然保存值域,也要保存结点和结 点之间的关系,实际中树有很多种表⽰⽅式如:双亲表⽰法,孩⼦表⽰法、孩⼦双亲表⽰法以及孩⼦ 兄弟表⽰法等。我们这⾥就简单的了解其中最常⽤的孩⼦兄弟表⽰法

struct TreeNode { struct Node* child; // 左边开始的第⼀个孩⼦结点 struct Node* brother; // 指向其右边的下⼀个兄弟结点 int data; // 结点中的数据域 };

1.4 树形结构实际运⽤场景 ⽂件系统是计算机存储和管理⽂件的⼀种⽅式,它利⽤树形结构来组织和管理⽂件和⽂件夹。在⽂件 系统中,树结构被⼴泛应⽤,它通过⽗结点和⼦结点之间的关系来表⽰不同层级的⽂件和⽂件夹之间 的关联。

2. ⼆叉树

2.1 概念与结构

在树形结构中,我们最常⽤的就是⼆叉树,⼀棵⼆叉树是结点的⼀个有限集合,该集合由⼀个根结点 加上两棵别称为左⼦树和右⼦树的⼆叉树组成或者为空。

从上图可以看出⼆叉树具备以下特点:

  • 1. ⼆叉树不存在度⼤于 2 的结点
  • 2. ⼆叉树的⼦树有左右之分,次序不能颠倒,因此⼆叉树是有序树

2.2 特殊的⼆叉树

满二叉树和名字一样,就是每层的节点数都到达最大数。

⼀个⼆叉树,如果每⼀个层的结点数都达到最⼤值,则这个⼆叉树就是满⼆叉树。也就是说,如果⼀ 个⼆叉树的层数为 K ,且结点总数是2^k-1.

2.2.2 完全⼆叉树

完全二叉树和满二叉树又不同,完全⼆叉树是效率很⾼的数据结构,完全⼆叉树是由满⼆叉树⽽引出来的。对于深度为 K 的,有 n 个 结点的⼆叉树,当且仅当其每⼀个结点都与深度为K的满⼆叉树中编号从 1 ⾄ n 的结点⼀⼀对应时称 之为完全⼆叉树。要注意的是满⼆叉树是⼀种特殊的完全⼆叉树。

2.3 ⼆叉树存储结构

2.3.1 顺序结构

无非就创建一个数组,挨个存 二叉树的数据,根节点无疑是0,然后他的两个孩子节点就是1和2,1的两个孩子节点就是4和5,以此类推。

2.3.2 链式结构

链式结构更容易想象到,就是每个节点有两个指向,一个指向左孩子,一个指向右孩子,然后每个节点都存储数据。

3. 实现顺序结构⼆叉树

顺序结构实现二叉树一般使用堆的方式,

堆又分为大堆和小堆

  • 小堆:根节点是最小的数据,每个节点都比他的父节点大
  • 大堆:和小堆刚相反,根节点最大,每个节点都比父节点大

 并且堆是一种完全而二叉树

3.2 堆的实现

头文件Heap.h

#include<stdio.h> #include<stdlib.h> #include<stdbool.h> #include<assert.h> typedef int HPDataType; typedef struct Heap { HPDataType* arr; int size; int capacity; }HP; void HPInit(HP* php); void HPPush(HP* php,HPDataType x); void HPPop(HP* php); void HPDestory(HP* php); bool HPEmpty(HP* php); 

Heap.c

#include"Heap.h" void HPInit(HP* php) { php->arr = NULL;//你的初始化有问题,这里size是多少你自己想想看呢 php->capacity = php->size=0; } void Swap(int* x, int* y) { int* tmp = *x; *x = *y; *y = *x; } void AdjustUp(HP* php) { int child = php->size - 1; int parent = (php->size - 1) / 2; while (child>0) { if (php->arr[parent] > php->arr[child]) { Swap(&php->arr[parent], &php->arr[child]); child = parent; parent = (child - 1) / 2; } else { break; } } } void HPPush(HP* php, HPDataType x) { assert(php); //判断空间是否足够 if (php->size == php->capacity) { //扩容 int newCapacity = php->capacity == 0 ? 4 : 2 * php->capacity;//所以到了这边你的cap也有问题导致你后面realloc出错 HPDataType* tmp = (HPDataType*)realloc(php->arr, newCapacity * sizeof(HPDataType)); if (tmp == NULL) { perror("realloc fail!"); exit(1); } php->arr = tmp; php->capacity = newCapacity; } php->arr[php->size] = x; AdjustUp(php); ++php->size; } void AdjustDown(HP* php) { int parent = 0; int child = 2 * parent + 1; while (child < php->size) { if (child + 1 < php->size && php->arr[child] > php->arr[child + 1]) { child++; } if (php->arr[parent] > php->arr[child]) { Swap(&php->arr[parent], &php->arr[child]); parent = child; child = parent * 2 + 1; } else { break; } } } void HPPop(HP* php) { Swap(&php->arr[0], &php->arr[php->size-1]); --php -> size; AdjustDown(php); } bool HPEmpty(HP* php) { assert(php); return php->size == 0; } void HPDestory(HP* php) { if (php->arr) free(php->arr); php->arr = NULL; php->size = php->capacity = 0; }

 3.2.2 向下调整算法

就是在删除堆顶的时候,将堆顶与最后一个元素进行交换,然后php->size--,从根节点挨个开始比较下一个节点的大小。

Read more

Flutter 三方库 shelf_modular 的鸿蒙化适配指南 - 掌控服务器路由资产、精密模块治理实战、鸿蒙级服务端专家

Flutter 三方库 shelf_modular 的鸿蒙化适配指南 - 掌控服务器路由资产、精密模块治理实战、鸿蒙级服务端专家

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 shelf_modular 的鸿蒙化适配指南 - 掌控服务器路由资产、精密模块治理实战、鸿蒙级服务端专家 在鸿蒙跨平台应用执行高级服务端管理与多维 Shelf 路由资产指控(如构建一个支持全场景秒级交互的鸿蒙大型全量后端服务中枢、处理海量 API Route Payloads 的语义认领或是实现一个具备极致指控能力的资产管理后台路由审计中心)时,如果仅仅依赖官方的基础 Shelf 处理器或者是极其繁琐的手动路由映射,极易在处理“由于模块嵌套导致的资产认领偏移”、“高频服务请求下的认领假死”或“由于多语言环境导致的符号解析冲突死结”时陷入研发代码服务端逻辑崩溃死循环。如果你追求的是一种完全对齐现代模块化标准、支持全量高度可定制路由(Modular-driven Backend)且具备极致指控确定性的方案。今天我们要深度解析的 shelf_modular——一个专注于解决“服务端资产标准化认领与模块化解耦”痛点的顶级工具库,正是帮你打造“鸿蒙超

By Ne0inhk
Flutter 三方库 wallet_connect 的鸿蒙化适配指南 - 实现 Web3 钱包协议连接、支持 DApp 授权登录与跨链交易签名实战

Flutter 三方库 wallet_connect 的鸿蒙化适配指南 - 实现 Web3 钱包协议连接、支持 DApp 授权登录与跨链交易签名实战

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 wallet_connect 的鸿蒙化适配指南 - 实现 Web3 钱包协议连接、支持 DApp 授权登录与跨链交易签名实战 前言 在进行 Flutter for OpenHarmony 的去中心化应用(DApp)或加密货币钱包开发时,支持标准的 WalletConnect 协议是链接用户钱包的关键。wallet_connect 是该协议的 Dart 实现,它能让你的鸿蒙 App 安全地与 MetaMask、Trust Wallet 等钱包建立双向加密连接。本文将探讨如何在鸿蒙系统下构建安全、稳定的 Web3 授权流程。 一、原理解析 / 概念介绍 1.1 基础原理

By Ne0inhk

【保姆级教程】从零部署宇树 Unitree 机器人 ROS 2 环境 (Go2/B2/H1) (Humble + 真实硬件)

摘要 本文为希望在ROS 2 (Humble) 环境下开发宇树 (Unitree) 机器人(支持 Go2, B2, H1)的开发者提供了一篇详尽的、从零开始的部署指南。我们将首先在 Ubuntu 22.04 上安装 ROS 2 Humble,然后重点讲解如何配置 unitree_ros2 功能包,实现 ROS 2 节点与机器人底层 DDS 系统的直接通信。本教程基于官方文档,并针对 Humble 环境进行了优化,可跳过 Foxy 版本复杂的 CycloneDDS 编译步骤。 核心环境: * 操作系统: Ubuntu 22.04 (Jammy) * ROS 2 版本: Humble

By Ne0inhk
Flash Table实测:JAI赋能低代码开发,重塑企业级应用构建范式

Flash Table实测:JAI赋能低代码开发,重塑企业级应用构建范式

目录 * 🔍 引言 * 1.1 什么是Flash Table * 1.2 低代码平台的进化与FlashTable的革新 * ✨FlashTable背景:为什么需要新一代低代码平台? * 2.1 传统开发的痛点 * 2.2 低代码平台的局限 * 2.3 FlashTable的差异化定位 * 💻 FlashTable安装:Docker部署&Jar包部署 * 3.1 基础环境要求 * 3.2 Docker部署(推荐方案) * 3.3 Jar包部署(无Docker环境) * 3.4 常见问题 * 📚FlashTable功能深度评测:从案例看真实能力 * 4.1 数据孤岛?FlashTable 自动化匹配字段 * 4.2 FlashTable复杂表单的开发挑战 * 4.3

By Ne0inhk