数据结构-二叉树-堆

news/2024/9/24 12:43:45/

一、物理结构和逻辑结构

在内存中的存储结构,逻辑结构为想象出来的存储结构。

二、完全二叉树的顺序存储结构

parent = (child - 1)/2

leftchild = 2*parent + 1;

rightchild = 2*parent +2

上面的顺序结构只适合存储完全二叉树。如果存储,会浪费很多的空间。

三、堆

1、堆的分类

小根堆:树中所有的父亲都小于或等于孩子。

大根堆:树中所有的父亲都大于或等于孩子。

接下来我们需要定义一个堆。定义过程如下:

创建堆的时候会涉及到一个向上调整的算法:我们可以画图表示这一过程

void UpAdjust(HPDataType* a, int child)
{assert(a);int parent = (child - 1) / 2;//建立大堆while (child > 0){if (a[child] > a[parent]){//交换两个数字Swap(&a[child], &a[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}
}

删除堆顶数据需要涉及到向下调整

这里不能挪动数据。原因有两个,效率低下,父子兄弟关系全乱了。

思路就是:把头部数据和尾部数据交换。删除尾部数据,然后进行向下调整

这样删除的优点是 效率高,保持了大部分堆的父子关系。

向下调整的过程中我们需要和儿子中最大的进行比较。这样才能保证堆的关系不变。

没有孩子时结束,转换一下就是child < size。

void DownAdjust(HPDataType* a,int parent,int size)
{int child = 2 * parent + 1;while (child < size){	//选出最大的那一个孩子if (child + 1 < size && a[child] < a[child + 1]){child++;}if (a[child] > a[parent]){//交换两个数字Swap(&a[child], &a[parent]);parent = child;child = 2 * parent + 1;}else{break;}}
}

整体实现

#include "heap.h"void HeapInit(HP* hp)
{assert(hp);hp->a = (HPDataType*)malloc(sizeof(HPDataType) * SIZE);hp->size = 0;hp->capacity = SIZE;
}void AddCapacity(HP* hp)
{assert(hp);if (hp->size == hp->capacity){HPDataType* temp = (HPDataType*)realloc(hp->a, sizeof(HPDataType) * hp->capacity * 2);if (temp == NULL){perror("realloc failed");return;}hp->a = temp;hp->capacity *= 2;}
}
void Swap(int* left, int* right)
{int temp = *left;*left = *right;*right = temp;
}
//除了child的位置,前面的数据构成堆
void UpAdjust(HPDataType* a, int child)
{int parent = (child - 1) / 2;//建立大堆while (child > 0){if (a[child] > a[parent]){//交换两个数字Swap(&a[child], &a[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}
}void HeapPush(HP* hp, HPDataType x)
{//考虑扩容的问题AddCapacity(hp);//插入数据hp->a[hp->size++] = x;//还需要考虑向上调整的问题。UpAdjust(hp->a, hp->size - 1);
}void DownAdjust(HPDataType* a,int parent,int size)
{int child = 2 * parent + 1;while (child < size){	//选出最大的那一个孩子if (child + 1 < size && a[child] < a[child + 1]){child++;}if (a[child] > a[parent]){//交换两个数字Swap(&a[child], &a[parent]);parent = child;child = 2 * parent + 1;}else{break;}}
}
//删除头部的数据
void HeapPop(HP* hp)
{assert(hp);assert(!HeapEmpty(hp));//首先交换头和尾的数字Swap(&hp->a[0], &hp->a[hp->size-1]);//然后删除尾的数字hp->size--;//向下调整恢复堆的原型 向下调整的左右子树一定是堆DownAdjust(hp->a, 0, hp->size);
}HPDataType HeapTop(HP* hp)
{assert(hp);return hp->a[0];
}
bool HeapEmpty(HP* hp)
{assert(hp);return hp->size == 0;
}
int HeapSize(HP* hp)
{assert(hp);return hp->size;
}

四、堆排

对数组进行排序。我们可以把它直接搞成一个堆,建堆操作

1、向上调整建堆

(1)把第一个数看成一个堆中的数。后来的数进行向上调整建立堆。 O(nlogn)

(2)排升序需要建大堆,减小堆关系就都乱了

利用向上调整建大堆时我们可以交换堆头和堆尾的值。然后在进行向下调整选出次小的值,如此往复。

堆排的过程如下

堆排代码:

void HeapSort(int* a,int n)
{//首先建立大堆for (int i = 1; i < n; i++){UpAdjust(a, i);}//交换堆头和堆尾的数字选出最大的数字放到堆尾//然后向下调整int end = n - 1;while (end > 0){Swap(&a[end], &a[0]);DownAdjust(a, 0, end);end--;}
}


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

相关文章

链路层安全扩展——L2TP协议

链路层安全扩展——L2TP协议 PPP协议 协议概念 说到数据链路层的安全协议&#xff0c;我们不得不先提一下PPP协议&#xff0c;后面的PAP、CHAP与L2TP协议都是围绕它展开的。&#xff08;PPP不是本文重点&#xff0c;很多细节没有提到&#xff0c;到时候会专开一篇文章讲PPP&…

ROS常用命令详解

摘要:ROS(Robot Operating System,机器人操作系统)是一个为机器人软件开发提供灵活框架的开源系统。在ROS中,常用命令是开发者进行机器人软件开发和调试的重要工具。本文将对ROS的常用命令进行详细介绍,包括节点管理、话题操作、消息查看、服务调用以及包管理等方面的命令…

【算法】基础算法003之二分

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》《算法》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 目录 前言 1.二分查找 朴素二…

Kafka重点笔记

Kafka重点笔记 默认端口号 9092 一、kafka将数据保存在哪里&#xff1f; kafka是将数据保存在磁盘。 二、离线计算、实时计算 离线计算&#xff1a;T1模式。处理的数据是静态数据&#xff0c;有界限&#xff0c;知道什么时候开始也知道什么时候结束。 实时计算&#xff1…

【数据结构】第二章 线性数据结构.线性表.单链表

第二章 线性数据结构.线性表.单链表 [5] 单链表的定义 1.单链表 逻辑结构&#xff1a;是一种线性表。 顺序表&#xff08;顺序存储&#xff09;&#xff1a; 优点&#xff1a;可随机存取&#xff0c;存储密度高缺点&#xff1a;要求大片连续空间&#xff0c;改变容量不方便…

【idea】idea 中 git 分支多个提交合并一个提交到新的分支

一、方法原理讲解 我们在 dev 分支对不同的代码文件做了多次提交。现在我们想要把这些提交都合并到 test 分支。首先我们要明白四个 git 操作&#xff0c; commit&#xff1a;命令用于将你的代码变更保存到本地代码仓库中&#xff0c;它创建了一个新的提交&#xff08;commit…

大数据Storm组件介绍

Storm 是一个开源的、分布式的实时计算系统&#xff0c;最初由Twitter开发并开源。它被设计用来处理大规模的实时数据流&#xff0c;并且具有高吞吐量、低延迟的特点。Storm 提供了一个简单而强大的编程模型&#xff0c;使得开发者可以轻松地编写复杂的实时数据处理应用。 以下…

Pandas——DataFrame对象用法

一、创建pandas的DataFrame对象 Pandas学习笔记二——创建pandas的DataFrame对象的3种方法 二、访问 Pandas DataFrame 中的元素 Python笔记&#xff1a;访问 Pandas DataFrame 中的元素 三、获取Dataframe的行数和列数 如何获取Dataframe的行数和列数 四、交换行 Panda…