看了左神的堆排序,觉得思路很清晰,比常见的递归的堆排序要更容易理解,所以自己整理了一下笔记,带大家一步步实现堆排序算法

首先介绍什么是大根堆:每一个子树的最大值都是子树的头结点,即根结点是所有结点的最大值

堆排序是基于数组和二叉树思想实现的(二叉树是脑补结构,实际是数组)

堆排序过程

1、数组建成大根堆,首先,遍历所有结点,当前结点index和父结点(index-1)/ 2 比较 (当前数组的下标是index,此结点的父结点的下标就是(index-1)/ 2  ),如果比父结点大,交换,变成父结点的位置再和上一层的父结点比较,直到满足大根堆条件

int swap(int source[], int a, int b)
{
int temp = source[a];
source[a] = source[b];
source[b] = temp;
}
int heapsort(int source[], int len)
{
for (int i = ; i <len; i++)
{
heapInsert(source, i);
}
}
int heapInsert(int source[], int index)
{
while (source[index] > source[(index - ) / ])
{
swap(source, index, (index - ) / );
index = (index - ) / ;
}
}

2、让根结点和最后一个结点交换位置,也就是数组的第一个数和最后一个数交换位置,接下来最后一个数不用考虑了,比如一个数组有5个数,定义一个变量size=5,大根堆的根结点放到最后一个数后,--size

int size = len;
swap(source, , --size);

3、让交换后的头结点经历一个向下的调整,让结点和自己的两个孩子比较,如果孩子的值比头结点大,交换,交换到孩子结点位置,继续和下面的两个孩子比较,直到满足大根堆条件

int heapify(int source[], int index, int size)//index表示要和它两个孩子比较的结点
{
int left = index * + ; //找到index左孩子结点的数组下标
while (left < size)
{
int largest = left + < size && source[left + ] > source[left] ? source[left + ] : source[left];//如果有右孩子且右孩子比左孩子大,令largest=右孩子的值,也就是把两个孩子中最大的一个数赋给largest
if (source[index] < source[largest])
{
swap(source, index, largest);
index = largest;
left = index * + ;
}
else break;
} }

4、重复第2步,第3步,直到size = 0 ,整个数组排序过程结束

while (size > )
{
swap(source, , --size);
heapify(source, , size);
}

源代码如下

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int swap(int source[], int a, int b)
{
int temp = source[a];
source[a] = source[b];
source[b] = temp;
}
int heapsort(int source[], int len)
{
for (int i = ; i < len; i++)
{
heapInsert(source, i);
}
int size = len;
while (size > )
{
swap(source, , --size);
heapify(source, , size);
}
}
int heapInsert(int source[], int index)
{
while (source[index] > source[(index - ) / ])
{
swap(source, index, (index - ) / );
index = (index - ) / ;
}
}
int heapify(int source[], int index, int size)//index表示要和它两个孩子比较的结点
{
int left = index * + ; //找到index左孩子结点的数组下标
while (left < size)
{
int largest = left + < size && source[left + ] > source[left] ? left + : left;//如果有右孩子且右孩子比左孩子大,令largest=右孩子的值,也就是把两个孩子中最大的一个数赋给largest
if (source[index] < source[largest])
{
swap(source, index, largest);
index = largest;
left = index * + ;
}
else break;
} }
int main()
{
int source[] = { ,,,,,,,,,,,,,,,,, };
int len;
len = sizeof(source) / sizeof(int);
heapsort(source, len);
for (int i = ; i < len; i++)
{
printf("%d ", source[i]);
} }

输出结果

以上就是堆排序的所有细节,这个版本很优良,堆排序的额外空间复杂度是O(1),如果用递归的话,递归有递归栈,额外空间复杂度不就上去了吗,设计成这种迭代的可以省空间,时间复杂度为O(n log n)

转载请注明出处、作者  谢谢

算法-一步步教你如何用c语言实现堆排序(非递归)的更多相关文章

  1. 自己写算法---java的堆的非递归遍历

    import java.io.*; import java.util.*; public class Main { public static void main(String args[]) { S ...

  2. 一步步教你轻松学奇异值分解SVD降维算法

    一步步教你轻松学奇异值分解SVD降维算法 (白宁超 2018年10月24日09:04:56 ) 摘要:奇异值分解(singular value decomposition)是线性代数中一种重要的矩阵分 ...

  3. 一步步教你轻松学支持向量机SVM算法之案例篇2

    一步步教你轻松学支持向量机SVM算法之案例篇2 (白宁超 2018年10月22日10:09:07) 摘要:支持向量机即SVM(Support Vector Machine) ,是一种监督学习算法,属于 ...

  4. 一步步教你轻松学支持向量机SVM算法之理论篇1

    一步步教你轻松学支持向量机SVM算法之理论篇1 (白宁超 2018年10月22日10:03:35) 摘要:支持向量机即SVM(Support Vector Machine) ,是一种监督学习算法,属于 ...

  5. 一步步教你轻松学主成分分析PCA降维算法

    一步步教你轻松学主成分分析PCA降维算法 (白宁超 2018年10月22日10:14:18) 摘要:主成分分析(英语:Principal components analysis,PCA)是一种分析.简 ...

  6. 一步步教你轻松学关联规则Apriori算法

    一步步教你轻松学关联规则Apriori算法 (白宁超 2018年10月22日09:51:05) 摘要:先验算法(Apriori Algorithm)是关联规则学习的经典算法之一,常常应用在商业等诸多领 ...

  7. 一步步教你轻松学K-means聚类算法

    一步步教你轻松学K-means聚类算法(白宁超  2018年9月13日09:10:33) 导读:k-均值算法(英文:k-means clustering),属于比较常用的算法之一,文本首先介绍聚类的理 ...

  8. 一步步教你轻松学朴素贝叶斯模型算法Sklearn深度篇3

    一步步教你轻松学朴素贝叶斯深度篇3(白宁超   2018年9月4日14:18:14) 导读:朴素贝叶斯模型是机器学习常用的模型算法之一,其在文本分类方面简单易行,且取得不错的分类效果.所以很受欢迎,对 ...

  9. 一步步教你轻松学KNN模型算法

    一步步教你轻松学KNN模型算法( 白宁超 2018年7月24日08:52:16 ) 导读:机器学习算法中KNN属于比较简单的典型算法,既可以做聚类又可以做分类使用.本文通过一个模拟的实际案例进行讲解. ...

随机推荐

  1. vuejs 使用less

    当所有东西都 准备好之后 : 第一步: 安装less依赖, npm install less less-loader --save 第二步: 修改webpack.config.js文件,配置loade ...

  2. ElasticSearch学习(一):ElasticSearch介绍

    一.ElasticSearch是什么? ElasticSearch是一款非常强大的.基于Lucene的开源搜索及分析引擎,可以帮助你从海量数据中,快速找到相关的数据信息. 比如,当你在GitHub上搜 ...

  3. python文件及路径管理函数

    glob模块 说明: 1.glob是python自己带的一个文件操作相关模块,用它可以查找符合自己目的的文件,就类似于Windows下的文件搜索, 支持通配符操作 *.?.[] 这三个通配符,*代表0 ...

  4. 使用Visual Studio Code进行MicroPython编程

    转载请注明文章来源,更多教程可自助参考docs.tpyboard.com,QQ技术交流群:157816561,公众号:MicroPython玩家汇 Visual Studio Code(以下简称VSC ...

  5. Spark2.4.0源码——DAGScheduler

    前言 Spark会将用户提交的作业看作一个job,在提交的时候首先将job转换为一系列的RDD,并按照RDD之间的依赖关系构建DAG(有向无环图),DAGScheduler会按照RDD依赖的不同将DA ...

  6. CSS3 入门级

    从刚开始学习的选择器总共有十三种: id class 标签 子代 后代 交集 并集 通配符 伪类 结构 属性 相邻 兄弟 (全当复习,如果有用的话那就正好) div[name=zhang]  这是属性 ...

  7. 数据结构与算法---查找算法(Search Algorithm)

    查找算法介绍 在java中,我们常用的查找有四种: 顺序(线性)查找 二分查找/折半查找 插值查找 斐波那契查找 1)线性查找算法 示例: 有一个数列: {1,8, 10, 89, 1000, 123 ...

  8. 致远A8任意文件写入漏洞_getshell_exp

    近期爆出致远 OA 系统的一些版本存在任意文件写入漏洞,远程攻击者在无需登录的情况下可通过向 URL /seeyon/htmlofficeservlet POST 精心构造的数据即可向目标服务器写入任 ...

  9. 如何搭建一个vue项目(完整步骤)

    参考资料 一.安装node环境 1.下载地址为:https://nodejs.org/en/ 2.检查是否安装成功:如果输出版本号,说明我们安装node环境成功 3.为了提高我们的效率,可以使用淘宝的 ...

  10. C++中 / 和 % 在分离各位时的妙用

    在学习c++的过程中,我们一般用 / 和 % 来分解数字的各个位 取整 (/) 比如1234 / 10 等于 123.4,这相当于把前三位分解出来了 取余(%) 比如 12345 的分解方法 个位:1 ...