c语言 最小值算法,C语言实现基于最大堆和最小堆的堆排序算法示例

堆定义堆实际上是一棵完全二叉树,其任何一非叶节点满足性质:

Key[i]<=key[2i+1]&&Key[i]<=key[2i+2](小顶堆)或者:Key[i]>=Key[2i+1]&&key>=key[2i+2](大顶堆)

即任何一非叶节点的关键字不大于或者不小于其左右孩子节点的关键字。

堆排序的思想利用大顶堆(小顶堆)堆顶记录的是最大关键字(最小关键字)这一特性,使得每次从无序中选择最大记录(最小记录)变得简单。

最大堆:所有节点的子节点比其自身小的堆。

最小堆:所有节点的子节点比其自身大的堆。

这里以最大堆为基础,其基本思想为:

1.将初始待排序关键字序列(R1,R2....Rn)构建成大顶堆,此堆为初始的无序区;

2.将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,......Rn-1)和新的有序区(Rn),且满足R[1,2...n-1]<=R[n];

3.由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,......Rn-1)调整为新堆,然后再次将R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2....Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成。

C语言实现

1.基于最大堆实现升序排序

// 初始化堆

void initHeap(int a[], int len) {

// 从完全二叉树最后一个非子节点开始

// 在数组中第一个元素的索引是0

// 第n个元素的左孩子为2n+1,右孩子为2n+2,

// 最后一个非子节点位置在(n - 1) / 2

for (int i = (len - 1) / 2; i >= 0; --i) {

adjustMaxHeap(a, len, i);

}

}

void adjustMaxHeap(int a[], int len, int parentNodeIndex) {

// 若只有一个元素,那么只能是堆顶元素,也没有必要再排序了

if (len <= 1) {

return;

}

// 记录比父节点大的左孩子或者右孩子的索引

int targetIndex = -1;

// 获取左、右孩子的索引

int leftChildIndex = 2 * parentNodeIndex + 1;

int rightChildIndex = 2 * parentNodeIndex + 2;

// 没有左孩子

if (leftChildIndex >= len) {

return;

}

// 有左孩子,但是没有右孩子

if (rightChildIndex >= len) {

targetIndex = leftChildIndex;

}

// 有左孩子和右孩子

else {

// 取左、右孩子两者中最大的一个

targetIndex = a[leftChildIndex] > a[rightChildIndex] ? leftChildIndex : rightChildIndex;

}

// 只有孩子比父节点的值还要大,才需要交换

if (a[targetIndex] > a[parentNodeIndex]) {

int temp = a[targetIndex];

a[targetIndex] = a[parentNodeIndex];

a[parentNodeIndex] = temp;

// 交换完成后,有可能会导致a[targetIndex]结点所形成的子树不满足堆的条件,

// 若不满足堆的条件,则调整之使之也成为堆

adjustMaxHeap(a, len, targetIndex);

}

}

void heapSort(int a[], int len) {

if (len <= 1) {

return;

}

// 初始堆成无序最大堆

initHeap(a, len);

for (int i = len - 1; i > 0; --i) {

// 将当前堆顶元素与最后一个元素交换,保证这一趟所查找到的堆顶元素与最后一个元素交换

// 注意:这里所说的最后不是a[len - 1],而是每一趟的范围中最后一个元素

// 为什么要加上>0判断?每次不是说堆顶一定是最大值吗?没错,每一趟调整后,堆顶是最大值的

// 但是,由于len的范围不断地缩小,导致某些特殊的序列出现异常

// 比如说,5, 3, 8, 6, 4序列,当调整i=1时,已经调整为3,4,5,6,8序列,已经有序了

// 但是导致了a[i]与a[0]交换,由于变成了4,3,5,6,8反而变成无序了!

if (a[0] > a[i]) {

int temp = a[0];

a[0] = a[i];

a[i] = temp;

}

// 范围变成为:

// 0...len-1

// 0...len-1-1

// 0...1 // 结束

// 其中,0是堆顶,每次都是找出在指定的范围内比堆顶还大的元素,然后与堆顶元素交换

adjustMaxHeap(a, i - 1, 0);

}

}

2.基于最小堆实现降序排序

// 初始化堆

void initHeap(int a[], int len) {

// 从完全二叉树最后一个非子节点开始

// 在数组中第一个元素的索引是0

// 第n个元素的左孩子为2n+1,右孩子为2n+2,

// 最后一个非子节点位置在(n - 1) / 2

for (int i = (len - 1) / 2; i >= 0; --i) {

adjustMinHeap(a, len, i);

}

}

void adjustMinHeap(int a[], int len, int parentNodeIndex) {

// 若只有一个元素,那么只能是堆顶元素,也没有必要再排序了

if (len <= 1) {

return;

}

// 记录比父节点大的左孩子或者右孩子的索引

int targetIndex = -1;

// 获取左、右孩子的索引

int leftChildIndex = 2 * parentNodeIndex + 1;

int rightChildIndex = 2 * parentNodeIndex + 2;

// 没有左孩子

if (leftChildIndex >= len) {

return;

}

// 有左孩子,但是没有右孩子

if (rightChildIndex >= len) {

targetIndex = leftChildIndex;

}

// 有左孩子和右孩子

else {

// 取左、右孩子两者中最上的一个

targetIndex = a[leftChildIndex] < a[rightChildIndex] ? leftChildIndex : rightChildIndex;

}

// 只有孩子比父节点的值还要小,才需要交换

if (a[targetIndex] < a[parentNodeIndex]) {

int temp = a[targetIndex];

a[targetIndex] = a[parentNodeIndex];

a[parentNodeIndex] = temp;

// 交换完成后,有可能会导致a[targetIndex]结点所形成的子树不满足堆的条件,

// 若不满足堆的条件,则调整之使之也成为堆

adjustMinHeap(a, len, targetIndex);

}

}

void heapSort(int a[], int len) {

if (len <= 1) {

return;

}

// 初始堆成无序最小堆

initHeap(a, len);

for (int i = len - 1; i > 0; --i) {

// 将当前堆顶元素与最后一个元素交换,保证这一趟所查找到的堆顶元素与最后一个元素交换

// 注意:这里所说的最后不是a[len - 1],而是每一趟的范围中最后一个元素

// 为什么要加上>0判断?每次不是说堆顶一定是最小值吗?没错,每一趟调整后,堆顶是最小值的

// 但是,由于len的范围不断地缩小,导致某些特殊的序列出现异常

// 比如说,5, 3, 8, 6, 4序列,当调整i=1时,已经调整为3,4,5,6,8序列,已经有序了

// 但是导致了a[i]与a[0]交换,由于变成了4,3,5,6,8反而变成无序了!

if (a[0] < a[i]) {

int temp = a[0];

a[0] = a[i];

a[i] = temp;

}

// 范围变成为:

// 0...len-1

// 0...len-1-1

// 0...1 // 结束

// 其中,0是堆顶,每次都是找出在指定的范围内比堆顶还小的元素,然后与堆顶元素交换

adjustMinHeap(a, i - 1, 0);

}

}

3.C语言版测试

大家可以测试一下:

// int a[] = {5, 3, 8, 6, 4};

int a[] = {89,-7,999,-89,7,0,-888,7,-7};

heapSort(a, sizeof(a) / sizeof(int));

for (int i = 0; i < sizeof(a) / sizeof(int); ++i) {

NSLog(@"%d", a[i]);

}

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

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

相关文章

LeetCode100 相同的树-简单

给你两棵二叉树的根节点 p 和 q &#xff0c;编写一个函数来检验这两棵树是否相同。 如果两个树在结构上相同&#xff0c;并且节点具有相同的值&#xff0c;则认为它们是相同的。 示例 1&#xff1a; 输入&#xff1a;p [1,2,3], q [1,2,3] 输出&#xff1a;true 示例 2&a…

Xamarin.Forms读取并展示Android和iOS通讯录 - TerminalMACS客户端

本文同步更新地址&#xff1a;https://dotnet9.com/11520.htmlhttps://terminalmacs.com/861.html阅读导航&#xff1a;一、功能说明二、代码实现三、源码获取四、参考资料五、后面计划一、功能说明完整思维导图&#xff1a;https://github.com/dotnet9/TerminalMACS/blob/mast…

LeetCode 101对称二叉树-简单

给定一个二叉树&#xff0c;检查它是否是镜像对称的。 例如&#xff0c;二叉树 [1,2,2,3,4,4,3] 是对称的。 1/ \2 2/ \ / \ 3 4 4 3但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的: 1/ \2 2\ \3 3代码如下&#xff1a; /*** Definition for a binary tree…

paragon+ntfs+linux,NTFS For Mac 超强兼容性

NTFS For Mac是为解决Windows和Mac OS X不兼容问题而开发的低级别档案系统驱动&#xff0c;提供在Mac OS X下完全读/写访问NTFS档案系统的任何版本。兼容mac OS X所有版本、32/64位内核模式&#xff0c;及其它第三方软件。不仅如此&#xff0c;NTFS For Mac 超强兼容性支持更多…

Asp.Net Core Ocelot Consul 微服务

做一个简单的微服务架构如下图&#xff1a;这个图表示的是一个网关代理Consul的两个服务&#xff0c;consul每个服务注册集群安装 Consul的服务&#xff0c;这里安装单机版的&#xff0c;集群版配置最低要求&#xff08;3个Consul server&#xff09;的需要三台虚拟机&#xff…

LeetCode 104二叉树的最大深度-简单

给定一个二叉树&#xff0c;找出其最大深度。 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。 说明: 叶子节点是指没有子节点的节点。 示例&#xff1a; 给定二叉树 [3,9,20,null,null,15,7]&#xff0c; 3/ \9 20/ \15 7返回它的最大深度 3 。 代码如下: …

以下c语言程序片段用于估测cpu的cache参数,阿里巴巴笔试题

阿里巴巴笔试题1.平均速度最快的排序算法是______。Shell排序快速排序冒泡排序插入排序2014-03-29 18:36:022.某服务进程的QPS(没秒处理的请求个数)较低&#xff0c;在空闲时间RT(响应时间)比较合理。在压力下CPU占用率20%左右。那么可能存在的问题是______。该进程的某个处理过…

.Neter们,你真的应该了解下EFCore3.x

本期导读&#xff1a;技术文&#xff0c;带你了解关于EntityFrameworkCore3.x的那些事&#xff0c;本文共1493个字&#xff0c;阅读大约需要3分钟。文末福利不要错过哦&#xff01;是的各位.Neter&#xff0c;不用怀疑&#xff0c;使用O/RM的开发者越来越多了&#xff0c;从风起…

LeetCode 111二叉树的最小深度-简单

给定一个二叉树&#xff0c;找出其最小深度。 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。 说明&#xff1a;叶子节点是指没有子节点的节点。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;2 示例 2&#xff1a; 输…

山东省中职信息技术c语言试题及答案,中职计算机专业C语言测试题

高三计算机专业C语言测试题(1)学号姓名&#xff1a;得分&#xff1a;一、选择题40’1、下列选项是C语言保留字的一项是()A DOB gosubC strutD CHAR2、下列选项中可以作为C语言用户标识符的一组是()A void , define, wordB a3_b3, _123, IFC for, _abc , caseD 2a, do, sizeof3、…

istio回归「单体应用」对我们的启发

大家好&#xff0c;我是Z哥。这次分享给大家的是一篇与技术相关的文章&#xff0c;但是我想表达的核心观点并不仅限于技术范围。我们中国有句古话&#xff0c;分久必合&#xff0c;合久必分。很多事物的发展都逃不开这个规律。如今&#xff0c;这件事也正在分布式、微服务概念大…

LeetCode 110平衡二叉树-简单

给定一个二叉树&#xff0c;判断它是否是高度平衡的二叉树。 本题中&#xff0c;一棵高度平衡二叉树定义为&#xff1a; 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;t…

c语言中如何使用面向对象编程,如何使用C语言的面向对象

我们都知道&#xff0c;C才是面向对象的语言&#xff0c;但是C语言是否能使用面向对象的功能&#xff1f;(1)继承性typedef struct _parent{int data_parent;}Parent;typedef struct _Child{struct _parent parent;int data_child;}Child;在设计C语言继承性的时候&#xff0c;我…

c语言开发环境 推荐,C语言复习和VC++6.0开发环境推荐.ppt

C语言复习和VC6.0开发环境推荐* * * * * * * * * F10-单步调试 F11-进入函数内部调试 ShiftF11-从函数内部回到调用函数(如main) CtrlF10-运行到光标处. ShiftF5-终止调试过程. * 是一个重要概念&#xff0c;可以有效地表示复杂的数据结构&#xff1b; 能动态分配内存&#xff…

LeetCode 112路径总和-简单

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum &#xff0c;判断该树中是否存在 根节点到叶子节点 的路径&#xff0c;这条路径上所有节点值相加等于目标和 targetSum 。 叶子节点 是指没有子节点的节点。 示例 1&#xff1a; 输入&#xff1a;root [5,4,8,11,…

ASP.NET MVC升级到ASP.NET Core MVC踩坑小结

写在前面ASP.NET Core是微软新推出的支持跨平台、高性能、开源的开发框架&#xff0c;它的优势不必多说&#xff0c;因为已经说得太多了。当然&#xff0c;现在依然有着数量庞大的系统运行于.NET Framework上&#xff0c;由于有大量的Break Changes&#xff0c;很多项目项目团队…

用函数求C15的值C语言,南开19春学期(1503、1509、1603、1609、1703)《C语言程序设计》在线作业-1辅导资料.docx...

南开19春学期(1503、1509、1603、1609、1703)《C语言程序设计》在线作业-1辅导资料.docx 南开19春学期(1503、1509、1603、1609、1703)C语言程序设计在线作业-11、D 2、B 3、C 4、A 5、D 一、单选题共40题&#xff0c;80分1、以下对一维整型数组 a 的正确说明是 Aint a10 ;Bint…

LeetCode 563二叉树的坡度-简单

给定一个二叉树&#xff0c;计算 整个树 的坡度 。 一个树的 节点的坡度 定义即为&#xff0c;该节点左子树的节点之和和右子树节点之和的 差的绝对值 。如果没有左子树的话&#xff0c;左子树的节点之和为 0 &#xff1b;没有右子树的话也是一样。空结点的坡度是 0 。 整个树…

c语言简单快速排序原理,C语言之简单快速排序

快速排序是一种对冒泡排序的改进&#xff0c;运用了二分的思想&#xff0c;提高了效率&#xff0c;元素的交换是跳跃式的&#xff0c;更适合用在数组这样方便随机读取的顺序结构&#xff0c;平均时间复杂度NlogN。#include #include /*快速排序*/void input(int*,int);void out…