算法-一步步教你如何用c语言实现堆排序(非递归)
看了左神的堆排序,觉得思路很清晰,比常见的递归的堆排序要更容易理解,所以自己整理了一下笔记,带大家一步步实现堆排序算法
首先介绍什么是大根堆:每一个子树的最大值都是子树的头结点,即根结点是所有结点的最大值
堆排序是基于数组和二叉树思想实现的(二叉树是脑补结构,实际是数组)

堆排序过程
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语言实现堆排序(非递归)的更多相关文章
- 自己写算法---java的堆的非递归遍历
import java.io.*; import java.util.*; public class Main { public static void main(String args[]) { S ...
- 一步步教你轻松学奇异值分解SVD降维算法
一步步教你轻松学奇异值分解SVD降维算法 (白宁超 2018年10月24日09:04:56 ) 摘要:奇异值分解(singular value decomposition)是线性代数中一种重要的矩阵分 ...
- 一步步教你轻松学支持向量机SVM算法之案例篇2
一步步教你轻松学支持向量机SVM算法之案例篇2 (白宁超 2018年10月22日10:09:07) 摘要:支持向量机即SVM(Support Vector Machine) ,是一种监督学习算法,属于 ...
- 一步步教你轻松学支持向量机SVM算法之理论篇1
一步步教你轻松学支持向量机SVM算法之理论篇1 (白宁超 2018年10月22日10:03:35) 摘要:支持向量机即SVM(Support Vector Machine) ,是一种监督学习算法,属于 ...
- 一步步教你轻松学主成分分析PCA降维算法
一步步教你轻松学主成分分析PCA降维算法 (白宁超 2018年10月22日10:14:18) 摘要:主成分分析(英语:Principal components analysis,PCA)是一种分析.简 ...
- 一步步教你轻松学关联规则Apriori算法
一步步教你轻松学关联规则Apriori算法 (白宁超 2018年10月22日09:51:05) 摘要:先验算法(Apriori Algorithm)是关联规则学习的经典算法之一,常常应用在商业等诸多领 ...
- 一步步教你轻松学K-means聚类算法
一步步教你轻松学K-means聚类算法(白宁超 2018年9月13日09:10:33) 导读:k-均值算法(英文:k-means clustering),属于比较常用的算法之一,文本首先介绍聚类的理 ...
- 一步步教你轻松学朴素贝叶斯模型算法Sklearn深度篇3
一步步教你轻松学朴素贝叶斯深度篇3(白宁超 2018年9月4日14:18:14) 导读:朴素贝叶斯模型是机器学习常用的模型算法之一,其在文本分类方面简单易行,且取得不错的分类效果.所以很受欢迎,对 ...
- 一步步教你轻松学KNN模型算法
一步步教你轻松学KNN模型算法( 白宁超 2018年7月24日08:52:16 ) 导读:机器学习算法中KNN属于比较简单的典型算法,既可以做聚类又可以做分类使用.本文通过一个模拟的实际案例进行讲解. ...
随机推荐
- flask(二)
1.装饰器坑 使用装饰器后,视图函数名字相同问题view function错误问题 1.给装饰器加functiontools 2.反向生成url地址标志,指定endpoint(endpoint必须唯一 ...
- 为什么Python中“2==2>1”结果为True
在Python中,你可能会发现这样一个奇怪的现象: >>> 2 == 2 > 1 True >>> (2 == 2) > 1 False >> ...
- C++标准库(体系结构与内核分析)(侯捷第一讲)
一.C++标准库介绍 C++标准库:C++ Standard Library C++标准库与STL有什么关系: STL:Standard Template Library STL包含6大部件,基本占标 ...
- 丢给你一个txt并同时获取你shell
丢给你一个txt并同时获取你shell 0x00:回顾 <文本编辑器Vim/Neovim被曝任意代码执行漏洞> 听闻很多人知道这个漏洞,但是有一部分人能复现成功,一部分人复现不出来.这里我 ...
- 手动搭建自己的nuget服务器及使用
这篇文章的主要目的: 1.搭建自己的私有的nuget服务器 2.打包代码为nuget包 3.在其他项目中使用私有服务器上的nuget包 一. 搭建自己的nuget服务器 1. 创建一个空的ASP.NE ...
- Android之LinearLayout布局下怎么让按钮固定在底部
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...
- django启动入口源码分析
manage.py是启动入口,在里面调用execute_from_command_line(sys.argv)方法 def execute_from_command_line(argv=None): ...
- 分享SQL,查询用户最近一次购买时间间隔
(1)先创建一张测试表: CREATE TABLE `用户购买订单` ( `购买时间` datetime(6) NULL DEFAULT NULL, `用户` varchar(20) CHARACTE ...
- html手机自适应屏幕
<meta name="viewport" content="height=device-width, initial-scale=1.0, maximum-sca ...
- Vue技术点整理-前言
前言 Vue版本说明:本文档编写时,Vue稳定版本为 2.6.10 本文档编写目的为:整理Vue相关生态的技术点.和开发中经常使用到的技术点,让开发者快速上手开发,提升开发效率 一,Vue开发工具:本 ...