数据结构-二叉树_堆

news/2024/11/22 7:55:08/

目录

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--,从根节点挨个开始比较下一个节点的大小。


http://www.ppmy.cn/news/1548978.html

相关文章

使用 Go 实现将任何网页转化为 PDF

在许多应用场景中&#xff0c;可能需要将网页内容转化为 PDF 格式&#xff0c;比如保存网页内容、生成报告、或者创建网站截图。使用 Go 编程语言&#xff0c;结合一些现有的库&#xff0c;可以非常方便地实现这一功能。本文将带你一步一步地介绍如何使用 Go 语言将任何网页转换…

【初阶数据结构与算法】线性表之队列的定义与实现

文章目录 一、队列的概念与结构1. 概念2.队列结构定义 二、队列的实现1.队列的初始化和销毁初始化销毁 2.队列的节点申请和入队列操作队列的节点申请入队列 3.队列的判空和出队列操作队列的判空出队列 4.取队头和队尾元素取队头元素取队尾元素 5.获取队列有效节点个数 三、队列…

【MogDB】MogDB5.2.0重磅发布第八篇-支持PLSQL编译全局缓存

前言 在我之前的文章中有提过&#xff0c;原生PG对于重度存储过程的应用系统适配&#xff0c;具有一个致命缺陷&#xff0c;即原生PG中的plsql是会话级缓存&#xff0c;这意味着每个会话在第一次执行某个存储过程时&#xff0c;都需要对这个存储过程进行编译&#xff0c;并且将…

.NET9 - 新功能体验(一)

被微软形容为“迄今为止最高效、最现代、最安全、最智能、性能最高的.NET版本”——.NET 9已经发布有一周了&#xff0c;今天想和大家一起体验一下新功能。 此次.NET 9在性能、安全性和功能等方面进行了大量改进&#xff0c;包含了数千项的修改&#xff0c;今天主要和大家一起体…

力扣 无重复字符的最长字串-3

无重复字符的最长字串-3 class Solution { public:// 解决方法&#xff1a;双指针int lengthOfLongestSubstring(string s) { // 如果字符串为空&#xff0c;直接返回0if (s.length() 0)return 0;// 如果字符串不为空&#xff0c;字符串每个字符都不同的情况下&#xff0c;最…

鸿蒙NEXT开发案例:血型遗传计算

【引言】 血型遗传计算器是一个帮助用户根据父母的血型预测子女可能的血型的应用。通过选择父母的血型&#xff0c;应用程序能够快速计算出孩子可能拥有的血型以及不可能拥有的血型。这个过程不仅涉及到了简单的数据处理逻辑&#xff0c;还涉及到UI设计与交互体验的设计。 【…

引用类型的局部变量线程安全问题分析——以多线程对方法局部变量List类型对象实例的add、remove操作为例

引用类型的局部变量线程安全问题 背景注意事项分析步骤拆解&#xff08;文字描述时序图&#xff09; 背景 最近博主在看B站上的一个JUC并发编程视频中&#xff0c;碰到了一个比较有争议性的局部变量线程安全讨论问题。 先贴代码如下&#xff1a; Slf4j(topic "c.Threa…

数组作为函数参数--选择排序

#include<stdio.h> #define n 6 void s(int a[])//写a的话&#xff0c;是地址 { int i,j; for(i0;i<n-2;i) { for(ji1;j<n-1;j) { if(a[j]<a[i]) { int ta[i]; a[i]a[j];…