排序算法-堆排序

来源:互联网 发布:什么数据库8000多 编辑:程序博客网 时间:2024/06/03 21:06

堆排序

算法描述

堆排序算法具有空间原址性,(二叉)堆是一个数组,它近似完全二叉树,树上的每一个节点对应数组中的一个元素,除了最底层外,该树是>完满的,而且从左向右填充。

最大堆性质

最大堆指的是对于某个节点,其值一定不小于其左右子节点的值,不大于其父节点的值: Arr[PARENT(i)]>=ARR[i]。

算法思想

首先,利用最大堆性质,将序列建成最大堆,因为数组中最大元素总在根节点Arr[1]中,通过把它与Arr[n]进行交换,然后将最后的节点从堆中去掉,新根节点可能会违背最大堆性质,因此对剩余节点进行调整以维护最大堆性质。因此算法步骤为:

  • 建立最大堆
  • 循环:
    • 交换堆中第一个元素与最后一个元素
    • 去除堆中最后一个节点
    • 维护最大堆性质

伪代码为:

  • HEAPOSORT(A)
    1. BUILD-MAX-HEAP(A)
    2. for i =A.length downto 2
    3.    exchange A[1] with A[i]
    4.    A.heap-size=A.heap-size-1
    5.    MAX-HEAPIFY(A,1)

算法实现(python)

 #-*- coding:utf-8 -*-heap_size=0b=[-1]def parent(i):  #求父节点的下标    return int(i/2)def left(i):    #求左孩子的下标    return 2*idef right(i):   #求右孩子的下标    return 2*i+1def add(a):    for i in a:        b.append(i)def maxHeapify(a,i):    #维持最大堆的性质    l=left(i)    r=right(i)    if (l<=heap_size) and (a[l]<a[i]):# and相当于java中的&&,会以“短路”的方式判断。从左到右计算表达式,若所有值均为真,则返回最后一个值,若存在假,返回第一个假值。# or也是从左到有计算表达式,返回第一个为真的值,相当于java中的||        largst=l    else:largst=i    if (r<=heap_size)and (a[r]<a[largst]):        largst=r    if (largst!=i):        t=a[i]        a[i]=a[largst]        a[largst]=t        maxHeapify(a, largst)    def buildMaxHeap():     #建立最大堆    #reversed会将列表元素反向排列并且返回,list.reverse()方法只讲列表反向排序不返回值。    for i in list(reversed(range(1,int(heap_size/2)+1))):        maxHeapify(b, i)def heapSort(a):      #堆排序算法,是一种原址排序法    add(a)    global heap_size,b   #在方法中修改全局变量的值时要加global关键字,否则直接赋值会创建相同名字的局部变量,并覆盖全局变量的值。    heap_size=len(b)-1    buildMaxHeap()    for i in list(reversed(range(1,len(b)))):        t=b[1]        b[1]=b[i]        b[i]=t        heap_size=heap_size-1        maxHeapify(b, 1)    del b[0] #del 可以按索引删除列表中元素,list.remove(obj)按元素删除    return bif __name__ =="__main__":    a=[2,4,3,9,7,5,77,5,12,5]    print heapSort(a)

算法复杂度

维护最大堆:时间复杂度为O(logn)
建立最大堆:线性时间复杂度
堆排序:时间复杂度为O(n*logn)


参考

《算法导论》第三版

原创粉丝点击