算法学习(二)——堆排序
堆排序是另一种排序算法,它是一种原地排序算法,其运行时间为O(nlgn),并且在任何时候,数组中只有常数个元素存储在数组以外。
在此之前要明确什么是堆,堆数组结构是一种数据对象,其可被视为是完全二叉树。树中每个结点与数组中的该结点值的那个元素对应。
表示堆的数组A有两个属性的对象:
length[A]是数组中的元素的个数
heap-size[A]是存放在A中的堆元素个数,也就是A[1..heap-size[A]]的元素是放在相应堆中,当然heap-size[A]]≤length[A]。
对于给定的某个结点i,
父结点下标: PARENT(i) return [i/2],(将i的二进制表示右移一位)
左儿子下标为 LEFT(i) return 2i ,(将i的二进制表示左移一位)
和右儿子的下标为 RIGHT(i) 2i+1。(将i的二进制表示左移移一位再在低位加一)
堆分最大堆和最小堆,暂且只讨论最大堆,除根结点以外的每个结点i,有A[PARENT[i]]≥A[i],即某个结点的值最多和其父结点的值一样大,所以根结点存放的即为堆的最大元素。
堆排序中有一些过程
对MAX-HEAPIFY(A, i)的调用,使得以i为根的子树成为最大堆,经过递归调用MAX-HEAPIFY(A, i)
MAX-HEAPIFY(A, i)
l ← LEFT(i) r ← RIGHT(i) if l ≤ heap-size[A] and A[l] > A[i] then largest ← l else largest ← i if r ≤ heap-size[A] and A[r] > A[largest] then largest ← r if largest ≠ i then exchange A[i] ↔ A[largest] MAX-HEAPIFY(A, largest)
建堆可以使用以下过程
BUILD-MAX-HEAP[A]
heap-size[A] = length[A] for i ← [length[A]/2] downto 1 do MAX-HEAPIFY(A, i)
不难看出大于[length[A]/2]的结点都是堆的叶子结点,因此不需要构建最大堆,对剩余的结点,以其为子树的根结点构建最大堆,依次循环至根结点,则整个数组对应的堆也是最大堆。
下面对数组A[1…n]进行排序
HEAPSORT[A] BUILD-MAX-HEAP[A] for i ← length[A] downto 2 do exchange A[1] ↔ A[i] heap-size[A] ← heap-size[A] - 1 MAX-HEAPIFY(A, 1)
首先构建最大堆,则根结点的元素为堆中的最大元素,从i为A的最末元素开始,将其与当前根元素替换,并且将i元素移出堆,再对剩下的堆元素进行MAX-HEAPIFY过程,构建最大堆。依次移除堆中的最大元素,按倒序仍然保存在数组A中,最终则对数组A完成了排序。