您的位置:首页 > 理论基础 > 数据结构算法

数据结构:堆排序

2016-12-18 21:24 218 查看
「仅为草稿,尚未详解」

堆排序(C语言版)

走进堆排序

什么是堆

堆实质就是一颗完全二叉树,其任何一非叶子节点满足下列性质。

  

i=1,2,3...n/2


说明:

  既然是完全二叉树,我们就可以用数组来表示!


堆根据上面的性质又分为:

  




  从中不难发现,大顶堆从上往下依次键值减小小顶堆从上向下键值增大

什么是堆排序

  ☐ 对一组待排序记录的关键字,首先把它们按堆的定义建成小(大)顶堆
  ☐ 然后输出堆顶的最小(大)关键字所代表的记录再对剩余的关键字建堆以便得到次小(大)的关键字
  ☐ 如此反复进行,直到全部关键字排成有序序列为止。

我们先对排序的过程进行了解(已经建好堆)

  我曾在优先队列的博客中介绍过大顶堆的这种构造新堆的方法:由上至下的堆有序化。这里同样类似。

  


♦我们如何将堆有序转换成我们想要的排序结果呢?

  即,我们想要将这颗完全二叉树变成结果:12 24 30 36 47 53 85 91..
  我们可以不断的执行上诉操作,即不断取出堆顶元素,然后再进行堆有序化,再取出堆顶元素,反复。

核心算法

  首先我们已经了解我们要操作堆本质是可以用数组来表示的完全二叉树。但是为了将堆排序的适用性增加,我们选用更加友好的顺序表(数组的增强版)来存储要排序的元素。

顺序表头文件的定义


头文件文件名: SqList.h

下面的所有函数


  


创建顺序表


只要输入非数字即可结束输入,如 12 36 24 85 47 30 53 91 a

该函数包括所有以下其他函数均放在[b]: SqList.cpp中,头部要 #include "SqList.h"。[/b]


  



堆有序的过程

  



说明:

  我再简单叙述一下,这个方法接收一个有序表(H)和开始调整的位置(s),截至位置(m).

  从s开始,我们判断它和它的子元素之间是不是符合小顶堆的定义,如果符合,我们就不调整了结束,但是如果不符合我们就找出子元素中最小的与它交换,

  交换以后,我们不能保证,它和子元素的子元素之间也符合小顶对定义,所以我们要循环判断,直到到达截至位置,也就是完全二叉树的最后一个位置。

  可能你会问了,为什么一旦碰到它和它的子元素之间符合小顶堆的定义,就结束调整呢?下面还可能会乱啊?

  下面会乱,我们就从最下面开始调整,先保证下面的是有序的,那样上面有序了下面那就不会乱了。请看下面剖析!


堆排序的过程

  


测试结果

  


算法分析

  时间复杂度:O(nlog2n) 空间复杂度:O(1)
  是一种不稳定的排序方法
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: