初阶数据结构:二叉树

目录

  • 1. 树的相关概念
    • 1.1 简述:树
    • 1.2 树的概念补充
  • 2. 二叉树
    • 2.1 二叉树的概念
    • 2.2 二叉树的性质
    • 2.3 二叉树的存储结构与堆
      • 2.3.1 存储结构
      • 2.3.2 堆的概念
      • 2.3.3 堆的实现
        • 2.3.3.1 堆的向上调整法
        • 2.3.3.2 堆的向下调整算法
        • 2.3.3.3 堆的实现

1. 树的相关概念

1.1 简述:树

树是一种非线性的数据结构,其有n个有限的节点构成,树结构具有层次性。它的形状颇像一颗颠倒的树,因此而被称为树。

补充:

  1. 树的结构中有一个特殊的结点,其没有前驱结点,被称为根结点。
  2. 树的结构中,其子树间不能存在交集,若存在交集,那么,此结构就不能被称为树结构。

1.2 树的概念补充

在这里插入图片描述

  1. 节点的度:一个节点含有的子树的个数称为该节点的度;(A结点的度为3)
  2. 叶子节点:度为0的结点;(E, F, G, D, H结点)
  3. 非叶子节点:度不为0的结点(B,C, G结点)
  4. 父亲节点:若一个节点含有子节点,则这个节点称为其子节点的父节点
  5. 子节点:一个节点含有的子树的根节点称为该节点的子节点;
  6. 兄弟节点:具有相同父节点的节点互称为兄弟节点;
  7. 树的度:一棵树中,最大的节点的度称为树的度;
  8. 节点的层 :从根开始定义起,根为第1层,根的子节点为第2层,以此类推;
  9. 树的深度 :树中节点的最大层次;
  10. 堂兄弟结点 :双亲在同一层的节点互为堂兄弟;
  11. 祖先结点:从根到该节点所经分支上的所有节点;
  12. 子孙结点 :以某节点为根的子树中任一节点都称为该节点的子孙;
  13. 森林: 多棵互不相交的树的集合

2. 二叉树

2.1 二叉树的概念

对于树结构的初次学习,我们来重点学习二叉树这一结构。

在这里插入图片描述

由上图可知,二叉树具有两个特点:

  1. 二叉树是一个结点的集合,可能为空或者由根节点,左子树,右子树构成。
  2. 二叉树由左右子树之分,所以,二叉树为一个有序树,其顺序不能颠倒。
  3. 二叉树的没有拥有超过两个孩子结点的结点,即二叉树的度为2
  4. 补充:特殊的二叉树
    <1> 满二叉树:除叶子结点外,所有结点都有左右孩子结点,若k二叉树的层数,那么满二叉树的结点就有 k 2 k^2 k2 - 1个结点。
    <2> 完全二叉树:除最后一层外,所有结点都有左右孩子结点,最后一层叶子结点连续

在这里插入图片描述

2.2 二叉树的性质

  1. 若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有2^(i - 1) 个结点.
  2. 若规定根节点的层数为1,则深度为h的二叉树的最大结点数是 2 h 2^h 2h - 1.(等比数列求和)
  3. 任何一棵二叉树, 如果度为0其叶结点个数为n, 则其度为0的结点一定比度为2的结点多一个.
  4. 若规定根节点的层数为1,具有n个结点的满二叉树的深度,h = l o g 2 ( n + 1 ) log_2(n + 1) log2(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否则无右孩子

2.3 二叉树的存储结构与堆

2.3.1 存储结构

  1. 顺序存储:
    其采用的方式为使用数组进行数据的存储,其各个结点的关系通过下标之间的数学关系来实现,在物理结构上其仍为数组,此结构只适合存储完全二叉树。
  2. 链式存储:
    使用链表的方式来存储数据,其存在三个域,数据域,左孩子指针域,右孩子指针域。在逻辑上,呈现链式的逻辑结构。

2.3.2 堆的概念

  1. 堆是一棵完全二叉树。
  2. 堆分为大堆与小堆,当所有结点的值都大于孩子结点时即为大堆,当所有结点的值都小于其孩子结点时即为小堆。

2.3.3 堆的实现

  1. 因为堆都是完全二叉树,这里我们使用顺序存储的方式来进行堆的实现。
  2. 在数组中若父亲节点的下标为pos,其左孩子的下标为pos × 2 + 1,右孩子结点的下标为pos × 2 + 2,下标为0的元素为根结点。(顺序存储方式,使用数组来实现堆结构的方式)

在这里插入图片描述

我们已经知晓了如何判断一个数组是否为堆,可我们对下面两个问题还是没有办法去解决:

  1. 当一个数组是堆时,我们如何保证在不断向数组中插入数据而堆的结构不被打乱。
  2. 如何将一个不是堆的数组调整为堆。
  3. 如何去创建一个是堆的数组。

我们接下来进行这几个问题的学习。

2.3.3.1 堆的向上调整法

在这里插入图片描述

void HeapAdjustUp(int* arr, int child)
{int parent = (child - 1) / 2;while (child > 0){if (arr[parent] < arr[child]){swap(&arr[parent], &arr[child]);child = parent;parent = (child - 1) / 2;}else{break;}}
}

向上调整建堆

  1. 将数组中的元素从首元素开始一个一个视作插入已有的堆中在进行向上调整,初始堆为空。

那么,我们就可以进行如下操作:

for(int i = 0; i < n; i++)
{HeapAdjustUp(arr, i);
}
2.3.3.2 堆的向下调整算法
void HeapAdjustDown(int* arr, int n, int parent)
{//n为元素个数int child = parent * 2 + 1;while (child < n){if (child + 1 < n && arr[child] < arr[child + 1]){child++;}if (arr[parent] < arr[child]){swap(&arr[parent], &arr[child]);parent = child;child = parent * 2 + 1;}else{break;}}
}

向下调整法建堆
2. 我们从最后一个非叶子结点开始,向下调整,调整过后的子树都为堆,一直循环到根结点。

操作如下:

过程演示:
在这里插入图片描述

for (int j = (n - 1 - 1) / 2; j >= 0; j--)
{HeapAdjustDown(arr, n, j);
}
2.3.3.3 堆的实现

堆的结构:

typedef struct Heap
{int* data;int size;int capacity;
}Heap;

堆的初始化与销毁:

void HeapInit(Heap* heap)
{heap->data = NULL;heap->capacity = heap->size = 0;
}void HeapDestroy(Heap* heap)
{while (heap->size){HeapPop(heap);}free(heap->data);heap->data = NULL;heap->capacity = heap->size = 0;
}

堆的元素增加与头删

void CheckCapacity(Heap* heap)
{if (heap->size == heap->capacity){int newcapacity = heap->capacity == 0 ? 4 : heap->capacity * 2;int* tmp = (int*)realloc(heap->data, newcapacity * sizeof(int));if (tmp == NULL){perror("malloc failed");exit(-1);}heap->data = tmp;heap->capacity = newcapacity;}
}void HeapPush(Heap* heap, int val)
{CheckCapacity(heap);heap->data[heap->size] = val;heap->size++;HeapAdjustUp(heap->data, heap->size - 1);
}//逆置首尾元素,size--,再向下调整
//向下调整后堆仍为堆的前置条件为,左右子树都为堆
void HeapPop(Heap* heap)
{assert(!HeapEmpty(heap));swap(&heap->data[0], &heap->data[heap->size - 1]);heap->size--;//左右子树都为堆HeapAdjustDown(heap->data, heap->size, 0);
}

返回堆顶元素与判空:

bool HeapEmpty(Heap* heap)
{return heap->size == 0;
}int HeapTop(Heap* heap)
{assert(!HeapEmpty(heap));return heap->data[0];
}

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

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

相关文章

MyBatis 学习(六)之动态 SQL

目录 1 动态 SQL 介绍 2 if 标签 3 where 标签 4 set 标签 5 trim 标签 6 choose、when、otherwise 标签 7 foreach 标签 8 bind 标签 1 动态 SQL 介绍 动态 SQL 是 MyBatis 强大特性之一&#xff0c;极大的简化我们拼装 SQL 的操作。MyBatis 的动态 SQL 是基于 OGNL 的…

网络编程(IP、端口、协议、UDP、TCP)【详解】

目录 1.什么是网络编程&#xff1f; 2.基本的通信架构 3.网络通信三要素 4.UDP通信-快速入门 5.UDP通信-多发多收 6.TCP通信-快速入门 7.TCP通信-多发多收 8.TCP通信-同时接收多个客户端 9.TCP通信-综合案例 1.什么是网络编程&#xff1f; 网络编程是可以让设…

【Vue3】PostCss 适配

px 固定的单位&#xff0c;不会进行自适应。rem r root font-size16px 1rem16px&#xff0c;但是需要手动进行单位的换算vw vh 相对于视口的尺寸&#xff0c;不同于百分比&#xff08;相对于父元素的尺寸&#xff09;375屏幕 1vw 3.75px 利用插件进行 px&#xff08;设计稿&…

SpringCloudAlibaba介绍

Spring Cloud Alibaba Spring Cloud Alibaba 是什么&#xff1f;微服务全景图核心特色 大家好&#xff0c;我叫阿明。下面我会为大家准备Spring Cloud Alibaba系列知识体系&#xff0c;结合实战输出案列&#xff0c;让大家一眼就能明白得技术原理&#xff0c;应用于各公司得各…

Github项目推荐-LightMirrors

项目地址 https://github.com/NoCLin/LightMirrors 项目简述 “LightMirrors是一个开源的缓存镜像站服务&#xff0c;用于加速软件包下载和镜像拉取。目前支持DockerHub、PyPI、PyTorch、NPM等镜像缓存服务。 当前项目仍处于早期阶段。”–来自项目说明。 也就是说&#xff…

如何解决线程安全问题(synchronized、原子性、产生线程不安全的原因,锁的特性,加锁的方式等等干货)

文章目录 &#x1f490;线程不安全的示例&#x1f490;锁的特性&#x1f490;产生线程不安全的原因&#xff1a;&#x1f490;加锁的三种方式 &#x1f490;线程不安全的示例 对于线程安全问题&#xff0c;这里用一个例子进行讲解&#x1f447;&#xff1a; 我现在定义一个变…

CTFHUB 命令执行

命令执行 原理&#xff1a; 在编写程序的时候&#xff0c;当碰到要执行系统命令来获取一些信息时&#xff0c;就要调用外部命令的函数&#xff0c;比如php中的exec()、system()等&#xff0c;如果这些函数的参数是由用户所提供的&#xff0c;那么恶意用户就可能通过构造命令拼…

MogaNet实战:使用MogaNet实现图像分类任务(一)

文章目录 摘要安装包安装timm 数据增强Cutout和MixupEMA项目结构计算mean和std生成数据集 摘要 论文&#xff1a;https://arxiv.org/pdf/2211.03295.pdf 作者多阶博弈论交互这一全新视角探索了现代卷积神经网络的表示能力。这种交互反映了不同尺度上下文中变量间的相互作用效…

微信小程序云开发教程——墨刀原型工具入门(编辑页面)

引言 作为一个小白&#xff0c;小北要怎么在短时间内快速学会微信小程序原型设计&#xff1f; “时间紧&#xff0c;任务重”&#xff0c;这意味着学习时必须把握微信小程序原型设计中的重点、难点&#xff0c;而非面面俱到。 要在短时间内理解、掌握一个工具的使用&#xf…

Django 管网项目 三

Django 官网文档 ​​Writing your first Django app, part 2 | Django documentation | Django 本文内容涉及创建视图 View&#xff0c;路由&#xff0c;和模版。并对内容进行渲染。 创建视图 在我们的投票应用中&#xff0c;我们需要下列几个视图&#xff1a; 问题索引页—…

阶跃信号与冲击信号

奇异信号&#xff1a;信号与系统分析中&#xff0c;经常遇到函数本身有不连续点&#xff08;跳变电&#xff09;或其导函数与积分有不连续点的情况&#xff0c;这类函数称为奇异函数或奇异信号&#xff0c;也称之为突变信号。以下为一些常见奇异函数。 奇异信号 单位斜变信号 …

ABAP - SALV教程07 斑马纹显示和SALV标题

SALV设置斑马纹和标题 METHOD set_layout.DATA: lo_display TYPE REF TO cl_salv_display_settings. * 取得显示对象lo_display co_alv->get_display_settings( ).* 设置ZEBRA显示lo_display->set_striped_pattern( X ). * 设置Titlelo_display->set_list_he…