算法导论之堆排序相关

来源:互联网 发布:老k平面户型优化设计 编辑:程序博客网 时间:2024/05/17 01:20
堆排序文档
二叉堆分为两种:最大堆、最小堆
最大堆:最大元素在根部,在堆的所有结点中,A[PATENT(i)]>=A[i]
最小堆:最小元素在根部,在堆的所有结点中,A[PATENT(i)]<=A[i]
下面以最大堆为例解释堆排序的具体过程:
首先会用到几个基本的函数:
PARENT(i)
Return ⌊i/2⌋
LEFT(i)
Return 2i
RIGHT(i)
Return 2i+1
这是三个基本函数,分别求的是二叉堆中第i个元素的父节点,左孩子结点和右孩子结点的标号
函数MAX-HEAPFY(A,i)是用来维护最大堆的基本性质,即就是(最大元素在根部,在堆的所有结点中,A[PATENT(i)]>=A[i]),函数的实现原理就是比较结点i的本身的值和此结点的左右子树的结点的值,将最大的值赋给结点i,即双亲结点。若是发生了变化,即就是原本最大的并不是根节点,后来进行了变换才将最大的值赋给了根节点,此时就要继续进行此操作,一直往下处理,直到不再发生变换时结束。函数MAX-HEAPFY(A,i)中,A代表的是存放数据的数组,i表示的要处理的结点的序号。

函数MAX-HEAPFY(A,i)的伪代码如下:


MAX-HEAPFY(A,i):
l=LEFT(i);
r=RIGHT(i);
if l<=A.heap-size && A[l]>A[i]
largest=l;
else largest=i;
if r<=A.heap-size && A[r]>A[largest]
largest=r;
if largest!=i
exchange A[i] with A[largest]

MAX-HEAPFY(A,largest)


其中,A.heap-size指的是数组A的有效的元素的个数(此函数的作用是,在一个元素的排列顺序满足堆的性质的数组中,变换了其中一个元素的位置,使得数组不再满足堆的性质的条件时,进行调整,使数组重新变得有序)
上面地函数MAX-HEAPFY(A,i)相当于创建了一个优先队列,下面要进行建堆:
用函数BUILD-MAX-HEAP(A)来实施建堆,此函数的本质是不断地调用函数MAX-HEAPFY(A,i),

对调换了第一个和最后一个元素的数组中元素的位置进行重新整理,使得元素之间满足堆的结构(注意堆的结构并不是按照从大到小的顺序从前到后进行排列)。


函数BUILD-MAX-HEAP(A)的伪代码如下:
BUILD-MAX-HEAP(A):
A.heap-size=A.length;
for i=⌊A.length/2⌋ downto 1

MAX-HEAPFY(A,i);


此函数执行完毕,存放原始数据的数组里的元素就按照最大堆的顺序排列好了,现在可以开始进行堆排序了

堆排序算法:基于前面的基础工作之上,堆排序算法的实现就变得很简单了,即就是首先建堆,然后将第一个元素和最后一个元素的位置互换,就得到了第一个元素,将它从原来的数组中单独拿出来,接着调用函数MAX-HEAPFY(A,i)来使堆维持其特性,再互换第一个元素和最后一个元素,就又可以得到一个新的元素,一直执行此操作,直到拿到了所有的元素。


堆排序算法的伪代码如下:
HEAPSORT(A):
BUILE-MAX-HEAP(A)
for i=A.length downto 2
exchange A[1] with A[i]
A.heap-size=A.heap-size-1;

MAX-HEAPFY(A,1)


堆排序算法HEAPSORT(A)的时间复杂度为O(nlgn),(性能最差的排序算法,例如冒泡和选择排序,他们的时间复杂度都是O(n*n))

由于快排的性能一般要优于堆排序,所以,与快排相比较,堆排序更大的用处体现在优先队列上。包含最大优先队列和最小优先队列。最大优先队列经常用于类似于操作系统中的共享计算机系统的作业调度;而最小优先队列经常用于基于事件驱动的模拟器。

0 0
原创粉丝点击