102.【C语言】数据结构之用堆对数组排序

server/2024/11/29 17:47:50/

0.前置知识

向上调整:

向下调整:

1.对一个无序的数组排升序和降序

排升序问题

建大根还是小根?

错误想法

由小根的定义:树中所有的父节点的值都小于或等于孩子节点的值,这样排出来的数组时升序的,建小根调用向上调整函数即可(把画圈的地方改成<即可)

arr未排序时,为{2,1,5,7,6,8,0,9,4,3}

4aa62cd67cae4cf5b3394957bc4d6b71.png

执行结果

显然不是升序

ade5d46e305a447fa284aeb6df796ff1.png

错误原因:忽略了一个严重的前提: 向上调整的前提:除了child位置,前面的数据结构构成

AdjustUp虽然找到了数组中最小的数,将其放到顶,但是顶的左右子树是无序的,必须将顶元素pop后才能选出剩余元素中最小的

解决方法

1.重新建:时间复杂度过高,不建议使用

2.建大根

代码

typedef int HPDataType;void Swap(HPDataType* p1, HPDataType* p2)
{HPDataType tmp = *p1;*p1 = *p2;*p2 = tmp;
}void AdjustUp(HPDataType* a, int child)
{int parent = (child - 1) / 2;while (parent>=0){if (a[child] > a[parent]){Swap(&a[parent], &a[child]);child = parent;parent = (parent - 1) / 2;}else{break;}}
}void AdjustDown(HPDataType* a, int n, int parent)
{int child = parent * 2 + 1;while (child < n){if (child+1 < n && a[child + 1] > a[child]){child++;}if (a[child] > a[parent]){Swap(&a[child], &a[parent]);parent = child;child = child * 2 + 1;}else{break;}}
}void HeapSort(int* arr, int n)
{for (int i = 1; i < n; i++){AdjustUp(arr, i);}int end = n - 1;while (end > 0){Swap(&arr[end], &arr[0]);AdjustDown(arr, end, 0);end--;}
}int main()
{int arr[] = {2,1,5,7,6,8,0,9,4,3};int size = sizeof(arr)/sizeof(arr[0]);HeapSort(arr,size);return 0;
}

运行结果

8ec18c10a508403cb321a13e3f07f109.png

细节分析

将HeapSort的while循环删掉,在return 0;处下断点,监视窗口查看arr

建大

 要好好利用大的这一个性质:顶元素的值永远是中元素的最大值

用while反复调整的过程可以描述为:

1=={大2,大1中最大的元素}

2=={大3,大2中最大的元素} -->大1=={大3,大2中最大的元素,大1中最大的元素}

3=={大4,大3中最大的元素}

...

(n-1)=={大n,大(n-1)中最大的元素}

将上方的式子合并起来,有

1={大n,大(n-1)中最大的元素,大(n-2)中最大的元素,...,大2中最大的元素,大1中最大的元素}

满足升序的要求

思考题

改动以上代码,使其对数组排降序

答案:理解上述分析的核心要点后,只需要改动几个不等号就可以了

typedef int HPDataType;void Swap(HPDataType* p1, HPDataType* p2)
{HPDataType tmp = *p1;*p1 = *p2;*p2 = tmp;
}void AdjustUp(HPDataType* a, int child)
{int parent = (child - 1) / 2;while (parent >= 0){if (a[child] < a[parent]){Swap(&a[parent], &a[child]);child = parent;parent = (parent - 1) / 2;}else{break;}}
}void AdjustDown(HPDataType* a, int n, int parent)
{int child = parent * 2 + 1;while (child < n){if (child + 1 < n && a[child + 1] < a[child]){child++;}if (a[child] < a[parent]){Swap(&a[child], &a[parent]);parent = child;child = child * 2 + 1;}else{break;}}
}void HeapSort(int* arr, int n)
{for (int i = 1; i < n; i++){AdjustUp(arr, i);}int end = n - 1;while (end > 0){Swap(&arr[end], &arr[0]);AdjustDown(arr, end, 0);end--;}
}int main()
{int arr[] = { 2,1,5,7,6,8,0,9,4,3 };int size = sizeof(arr) / sizeof(arr[0]);HeapSort(arr, size);return 0;
}

运行结果


http://www.ppmy.cn/server/145953.html

相关文章

字符函数和字符串函数

字符分类函数 C语言中有⼀系列的函数是专门做字符分类的&#xff0c;也就是⼀个字符是属于什么类型的字符的。 这些函数的使用都需要包含⼀个头文件&#xff1a;ctype.h 这些函数的用法非常类似。 int islower ( int c )islower是能够判断参数部分是否是小写字母的。 通过返…

虚幻引擎---目录结构篇

一、引擎目录 成功安装引擎后&#xff0c;在安装路径下的Epic Games目录中可以找到与引擎版本对应的文件夹&#xff0c;其中的内容如下&#xff1a; Engine&#xff1a;包含构成引擎的所有源代码、内容等。 Binaries&#xff1a;包含可执行文件或编译期间创建的其他文件。Bui…

torch.is_nonzero(input)

torch.is_nonzero(input) input: 输入张量 若输入是 不等于零的单元素张量 则返回True&#xff0c;否则返回False 不等于零的单元素张量&#xff1a;torch.tensor([0.]) 或 torch.tensor([0]) 或 torch.tensor([False])单元素张量: 只有一个数 的张量 import torch print(t…

【插入排序】:直接插入排序、二分插入排序、shell排序

【插入排序】&#xff1a;直接插入排序、二分插入排序、shell排序 1. 直接插入排序1.1 详细过程1.2 代码实现 2. 二分插入排序2.1 详细过程2.2 代码实现 3. shell排序3.1 详细过程3.2 代码实现 1. 直接插入排序 1.1 详细过程 1.2 代码实现 public static void swap(int[]arr,…

Vue源码巧妙设计

Vue.js的源码中蕴含了许多巧妙的设计&#xff0c;这些设计使得Vue成为一个高效、灵活且易于使用的前端框架。以下是对Vue源码中一些巧妙设计的详细讲解&#xff1a; 1. 响应式系统 Vue的响应式系统是其核心特性之一&#xff0c;它允许Vue追踪数据的变化&#xff0c;并在数据变…

MySql之MVVC总结

多版本并发控制MVVC&#xff0c;Multi-Version Concurrency Control,通过数据行的多个版本来控制数据库的并发。mysql只有InnoDB引擎才支持MVVC. 通过管理每条记录的多个版本&#xff0c;实现数据库事务并发时一致性读&#xff0c;当前事务A读取正在被其他事务B更新的数据行时…

使用 Canal 实时从 MySql 向其它库同步数据

目前绝大多数项目还是采用 mysql 作为数据存储&#xff0c;对于用户访问量较高的网站来说&#xff0c;mysql 读写性能有限&#xff0c;我们通常会把 mysql 中的数据实时同步到 Redis、mongodb、elastic search 等中间件中&#xff0c;应对高并发访问场景&#xff0c;减轻 mysql…

知识图谱嵌入评估的常用任务

知识图谱嵌入&#xff08;KGE&#xff09;是通过将图中的实体和关系表示为低维向量&#xff0c;从而使得原本复杂的图结构可以被机器学习模型处理&#xff0c;并用于后续任务。有效的评估方法能够帮助研究者和工程师了解模型在不同任务中的表现&#xff0c;并优化模型以提升其在…