初阶数据结构:二叉树

目录

  • 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.mzph.cn/news/715608.shtml

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

相关文章

【C++ AVL树】

文章目录 AVL树AVL树的概念AVL树节点的定义AVL树的插入AVL树的旋转右单旋左单旋左右双旋右左双旋 代码实现 总结 AVL树 AVL树的概念 二叉搜索树在顺序有序或接近有序的情况下&#xff0c;而插入搜索树将退化为单叉树&#xff0c;此时查找的时间复杂度为O(n)&#xff0c;效率低…

鸿蒙Harmony应用开发—ArkTS声明式开发(通用属性:颜色渐变)

设置组件的颜色渐变效果。 说明&#xff1a; 从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 linearGradient linearGradient(value: { angle?: number | string; direction?: GradientDirection; colors: Array; repea…

mamba-ssm安装building wheel卡着不动后error...避坑解决方法

文章目录 方法1、下载whl文件到本地后pip install安装成功后验证&#xff1a; 方法2、拉取Docker镜像 对于项目中用到MambaIR的小伙伴&#xff0c;需要pip安装 causal_conv1d和 mamba-ssm两个包及其依赖&#xff1a; torch packing transformersMambaIR-Github主页&#xff0…

【C++】vector的使用及其模拟实现

这里写目录标题 一、vector的介绍及使用1. vector的介绍2. 构造函数3. 遍历方式4. 容量操作及空间增长问题5. 增删查改6. vector二维数组 二、vector的模拟实现1. 构造函数2. 迭代器和基本接口3. reserve和resize4. push_back和pop_back5. insert和erase5. 迭代器失效问题5. 浅…

【Java】基础算法练习题

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ 目录 基础算法练习题&#x1f680;1. 两数之和…

Django 管网项目 三

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

ChatGPT支持下的PyTorch机器学习与深度学习技术应用

近年来&#xff0c;随着AlphaGo、无人驾驶汽车、医学影像智慧辅助诊疗、ImageNet竞赛等热点事件的发生&#xff0c;人工智能迎来了新一轮的发展浪潮。尤其是深度学习技术&#xff0c;在许多行业都取得了颠覆性的成果。另外&#xff0c;近年来&#xff0c;Pytorch深度学习框架受…

相关知识1111

一、 店铺编号和相关负责人 1、天猫兄弟、锦格 京东凡越 福林哥 如萍姐 2、京东锦格 天猫凡越 林森 雷佳华 3、天猫从简 京东从简 孔哥 4、抖音锦格 拼多多凡越 鸿哥 不知道哪个店铺编号&#xff1a;0 二、天猫京东聊天界面快捷搜索商品 1、 天猫只能根据标题搜索 2、京东是…

神经网络之万能定理python-pytorch实现,可以拟合任意曲线

神经网络之万能定理python-pytorch实现&#xff0c;可以拟合任意曲线 博主&#xff0c;这几天一直在做这个曲线拟合的实验&#xff0c;讲道理&#xff0c;网上可能也有很多这方面的资料&#xff0c;但是博主其实试了很多&#xff0c;效果只能对一般的曲线还行&#xff0c;稍微…

java之抽象类

什么是抽象类&#xff1f; 抽象就是不能具体化&#xff0c;不能实例化 作为父类&#xff0c;让子类去实现 abstract修饰类就是抽象类 abstract修饰方法就是抽象方法修饰符 abstract class 类名{修饰符 abstract 返回值类型 方法名(形参列表); }public abstract class A {//不…

CTFHUB--文件包含漏洞--RCE

文件包含漏洞 文件包含漏洞也是一种注入型漏洞&#xff0c;其本质就是输入一段用户能够控制的脚本或者代码&#xff0c;并让服务端执行。有时候由于网站功能需求&#xff0c;会让前端用户选择要包含的文件&#xff0c;而开发人员又没有对要包含的文件进行安全考虑&#xff0c;…

CSS【详解】居中对齐 (水平居中 vs 垂直居中)

水平居中 内部块级元素的宽度要小于容器(父元素) 方案一&#xff1a;文本居中对齐&#xff08;内联元素&#xff09; 限制条件&#xff1a;仅用于内联元素 display:inline 和 display: inline-block; 给容器添加样式 text-align:center<!DOCTYPE html> <html lang&q…

【简略知识】项目开发中,VO,BO,PO,DO,DTO究竟是何方妖怪?

前言 在项目开发中&#xff0c;是否需要定义VO&#xff08;视图对象&#xff09;&#xff0c;BO&#xff08;业务对象&#xff09;&#xff0c;PO&#xff08;持久化对象&#xff09;&#xff0c;DO&#xff08;领域对象&#xff09;&#xff0c;DTO&#xff08;数据传输对象&…

笨办法学 Python3 第五版(预览)(三)

原文&#xff1a;Learn Python the Hard Way, 5th Edition (Early Release) 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 练习 30&#xff1a;假如 这是你将要输入的下一个 Python 脚本&#xff0c;它向你介绍了if语句。输入这个代码&#xff0c;确保它能够完美运行…

Home-credit海外贷款信贷产品源码/线上贷款产品大全/贷款平台软件源码/海外借贷平台

测试环境&#xff1a;Linux系统CentOS7.6、宝塔、PHP7.3、MySQL5.6&#xff0c;根目录public&#xff0c;伪静态laravel5&#xff0c;开启ssl证书 语言&#xff1a;中文简体、英文 laravel框架的程序有点多&#xff0c;这个团队估计主要就是搞laravel开发的&#xff0c;基本上…

YOLOv9独家原创改进|增加SPD-Conv无卷积步长或池化:用于低分辨率图像和小物体的新 CNN 模块

专栏介绍&#xff1a;YOLOv9改进系列 | 包含深度学习最新创新&#xff0c;主力高效涨点&#xff01;&#xff01;&#xff01; 一、文章摘要 卷积神经网络(CNNs)在计算即使觉任务中如图像分类和目标检测等取得了显著的成功。然而&#xff0c;当图像分辨率较低或物体较小时&…

可以用来测试的接口

实际开发过程中&#xff0c;我们可以通过postman工具来测试接口 get请求 https://api.github.com/events?id1&nameuser post请求 http://httpbin.org/post 参数1&#xff1a;key1value1 参数2&#xff1a;key2value2

(C语言)回调函数

回调函数是什么&#xff1f; 回调函数就是⼀个通过函数指针调⽤的函数。 如果你把函数的指针&#xff08;地址&#xff09;作为参数传递给另⼀个函数&#xff0c;当这个指针被⽤来调⽤其所指向的函数 时&#xff0c;被调⽤的函数就是回调函数。回调函数不是由该函数的实现⽅…

技术阅读周刊第十四期:常用的 Git 配置

技术阅读周刊&#xff0c;每周更新。 历史更新 20231122&#xff1a;第十一期20231129&#xff1a;第十二期20240105&#xff1a;第十三期&#xff1a;一些提高生产力的终端命令20240112&#xff1a;第十四期&#xff1a;Golang 作者 Rob Pike 在 GopherConAU 上的分享 How I w…

探索Manticore Search:开源全文搜索引擎的强大功能

在当今信息爆炸的时代&#xff0c;数据的快速检索变得至关重要。无论是在电子商务网站、新闻门户还是企业内部文档&#xff0c;高效的搜索引擎都是确保用户满意度和工作效率的关键因素之一。而在搜索引擎领域&#xff0c;Manticore Search 作为一款开源的全文搜索引擎&#xff…