堆排序原理及实现

堆排序原理及实现

概述

​ 排序算法在程序设计中属于使用频度很高的一类算法,好的排序算法对于程序效率的提升有一定作用。常见的简单排序算法如冒泡排序、插入排序,对于多数情况来说O(n^2)的时间复杂度并不是太理想,效果较好的归并排序倒是时间复杂度达到O(n * lgn)了,可惜要使用额外的数组空间。所幸,有一种和归并排序效率差不多的原地排序算法——堆排序。这里就记录一下堆排序的原理及实现细节。

堆的基本性质

​ 堆是一种数据结构,在堆排序中用到的堆则更特殊一点,是二叉堆。结构类似于二叉树,每个节点至多有2个子节点,它可以近似被看作一个完全二叉树,除了最底下的一层外,其它层都是被充满的。

​ 常见的二叉堆实现是数组形式,因为二叉堆的父子节点在数组中索引有明确的数学关系:

Left(i) = i * 2, Right(i) = i * 2 + 1, i是当前节点索引,Left表达式求解当前节点的左子节点索引,Right表达式求解当前节点的右子节点索引。

​ 二叉堆可以分为2种形式,一种是最大堆,一种是最小堆。2种形式在结构上是相似的,只是性质不同。

​ 对于最大堆:Array[Parent(i)] >= Array[i],该性质用文字描述可以这么表示,任一节点值(除根节点以外)小于或等于其父节点值。

​ 对于最小堆:Array[Parent(i)] <= Array[i],该性质用文字描述可以这么表示,任一节点值(除根节点以外)大于或等于其父节点值。

维护堆性质(以最大堆为例)

​ 维护堆性质,对于堆添加新元素或改变元素值时是很重要的一步。对于最大堆来说,任一节点值(除根节点外)小于等于其父节点值,也就是说,任一节点值必定大于等于其左右子树的所有节点值,当这一性质不满足时,我们需要做的处理是,在其左右子树中找出一个值最大的节点让它”上浮”到当前节点,而当前节点则应该逐层”下沉”到一个合适的位置。这就是维护堆性质的办法。

你可能感兴趣的:(数据结构与排序算法,数据结构,排序算法,堆排序)