堆排其实就是选择排序,只不过用了完全二叉树特性。

      堆排思想 : 利用完全二叉树特性建堆和重复选择调整来得到有序数组

      完全二叉树有什么特性呢? 节点左对齐 ---> 层序遍历不会出现空,可以用数组表达(访问效率高)

      那么可以将它映射到数组上,并且遵循一个规律: 设i为当前节点索引,

         i->left = 2*i+1              i->right = 2*i+2   可得-->

      i = (i->left-1)/2 = (i->right-2)/2  = (i->left-2 +1)/2 = (i->left-2)/2 + 1/2(计算机整除为0) = (i->child-1)/2

       

  

     堆排序种类:

       大根堆 : parent > left && right   ---> 升序

       小根堆 : parent < left && right   ---> 降序

       堆排序最经典的问题就是topK问题。

      

      堆排过程(假如要降序) :

      1. 建小堆    

                   

              建小堆过程:  1.找到最后一个非叶子节点(叶子节点不用调整,因为向下调整前提是有孩子),进行向下调整 

                     2.依次向前将所有非叶子节点调整完,小堆也就构建好了

              1.选最后一个非叶子节点 3,向下调整

            

                2.继续找倒数第二个非叶子节点向下调整,重复直到全部非叶子节点调整完成

              此时,小堆建立完成,堆顶为数组中最小值

      

      2. 向下调整      `

             向下调整过程: 1.小堆顶部是最小值,将其与最后一个节点交换,最小值固定

                     2.将根节点与最小的孩子节点比较,若是不是最小值则交换,继续调整递归比较,找到合适的位置,再次形成小堆

                     3.循环1,2步骤直到所有值固定  

      1.交换1和3,固定1 

       

     2.向下调整形成小堆

       3.重复1,2步骤直到固定所有值

     

     C/C++代码demo:

 #include<algorithm>
//向下调整
//和孩子比较,小了退出,大了交换
void AdjustDown(int* arr,int n,int root)
{
int parent = root;
int child = root* + ;
//交换边界: 交换到最后的位置了
while(child<n)
{
//找最小的孩子
if(child+<n && arr[child]>arr[child+])
{
++child;
}
//大了交换,并更新父子节点
if(arr[parent]>arr[child])
{
swap(arr[parent], arr[child]);
parent = child;
child = *parent+;
}
//小了退出
else
{
break;
}
}
} //堆排序 --- 降序,造小堆
// 下标获取方法:
// i->left = i*2 + 1 i->right = i*2 + 2
// i = (i->child-1) * 2
void HeapSort(int* arr,int n)
{
//1.建堆 --- 从最后一个非叶子节点依次向下调整
//最后一个非叶子节点确定方法: n-1的父亲,因为左对齐,所以此位置前面都有孩子
for(int i=(n-)/;i>=;--i)
AdjustDown(arr,n,i); //2.向下调整 --- 重复交换,固定,向下调整直到全部固定
for(int end=n-;i>;--i){
swap(arr[],arr[end])
AdjustDown(arr,n-,i);
}
}

    

DS 图解堆排的更多相关文章

  1. DS 图解快排

    快速排序是交换排序,是冒泡排序的改进版. 快排过程: 1.选定一个分界值     2.分成三个部分(小于分界部分,分界值,大于分界值部分)                       3.对于分开的两 ...

  2. DS 图解归并排序

    经典排序三剑客: 归并,堆排,快排. 今天,图解归并,一步步带你手撕代码~ 归并排序,是采用"分而治之"思想的一个典型应用. 分治法精髓: 1.分 --- 将问题分解成若干个规模更 ...

  3. 数组第K小数问题 及其对于 快排和堆排 的相关优化比较

    题目描述 给定一个整数数组a[0,...,n-1],求数组中第k小数 输入描述 首先输入数组长度n和k,其中1<=n<=5000, 1<=k<=n 然后输出n个整形元素,每个数 ...

  4. 【Algorithm】堆排,C++实现

    对一个数组中的元素按照顺序构建二叉树,就形成了一个(二叉)堆.(二叉树是虚拟的,并不是真的建立二叉树) 表示堆的数组A有两个重要属性:A.heapSize,表示堆里面有多少元素,数组里有多少元素在堆里 ...

  5. 造轮子-Java泛型堆排

    个人博客地址:http://kyle.org.cn/2018/03/13/heapsort/ Java实现泛型堆排算法,用于N个对象中选择最大或者最小的前M个,其中M<=N 类似于Mysql中o ...

  6. P1177 【模板】快速排序(学完归并和堆排之后的二更)

    P1177 [模板]快速排序 不用说,连题目上都标了是一道模板,那今天就来对能用到的许多排序方式进行一个总结: 选择排序 选择排序(Selection sort)是一种简单直观的排序算法.它的工作原理 ...

  7. 图解堆算法、链表、栈与队列(Mark)

    原文地址: 图解堆算法.链表.栈与队列(多图预警) 堆(heap),是一类特殊的数据结构的统称.它通常被看作一棵树的数组对象.在队列中,调度程序反复提取队列中的第一个作业并运行,因为实际情况中某些时间 ...

  8. 排序算法C语言实现——冒泡、快排、堆排对比

    对冒泡.快排.堆排这3个算法做了验证,结果分析如下: 一.结果分析 时间消耗:快排 < 堆排 < 冒泡. 空间消耗:冒泡O(1) = 堆排O(1) < 快排O(logn)~O(n) ...

  9. python 快排,堆排,归并

    #归并排序 def mergeSort(a,L,R) :     if(L>=R) :         return     mid=((L+R)>>1)     mergeSort ...

随机推荐

  1. SQL进阶-数据类型转换

    一般有这几种转换: 一.数值型与字符型的转化 ### 数值型转为字符型: –> '65' select cast(65 as char); –> 'A' select char(65); ...

  2. 本地局域网yum源搭建-centos/redhat

    环境-centos6.7  [本机yum搭建提前备好,不做介绍] [root@nagios ~]# cat /etc/redhat-release CentOS release 6.7 (Final) ...

  3. Linux kill、kill-15、kill-9区别

    进程状态转换图 kill和kill -9,两个命令在linux中都有杀死进程的效果,然而两命令的执行过程却大有不同,在程序中如果用错了,可能会造成莫名其妙的现象. 执行kill(不加 -* 默认kil ...

  4. ImportError: this is MySQLdb version (1, 2, 5, 'final', 1), but _mysql is version (1, 4, 4, 'final', 0)

    (flask-demo) ➜ flask-demo git:(master) ✗ pip install mysqlclient==1.2.5 DEPRECATION: Python 2.7 will ...

  5. async异步流程控制神器

    async https://www.npmjs.com/package/async Async is a utility module which provides straight-forward, ...

  6. Jenkins build 后 tomcat 启不来

    Jenkins build 后 war 包复制到 tomcat 下,启不来 添加 :export BUILD_ID=dontKillMe /usr/local/iron/tomcat8085/bin/ ...

  7. SDN实验---OVS了解(转载)

    转载自:https://opengers.github.io/openstack/openstack-base-use-openvswitch/ 一:Open vSwitch介绍 (一)介绍 在过去, ...

  8. 如何利用maven将本地jar包引入到工程之中

    1.在个人开发模式下,可以将jar包放入项目的lib目录中,在pom.xml中做如下配置: <dependencies> <dependency> <groupId> ...

  9. JS调用onBackPressed

    需求: 安卓页面webview加载H5页面,H5页面能能返回到安卓页面 import android.os.Bundle; import android.support.v7.app.AppCompa ...

  10. 为什么0x00400000是可执行文件的默认基址?EXE base address start with 400000H,Why is 0x00400000 the default base address for an executable?

    DLL的默认基址是0x10000000,但EXE的默认基址是0x00400000.为什么EXE特别值?4 兆字节有什么特别之处它与x86上单页目录条目映射的地址空间量和1987年的设计决策有关.对EX ...