数据科学家成长之旅

关注 机器学习,深度学习,自然语言处理,数学

排序算法(7)——堆排序

__author__ = 'steven'
# coding=utf-8
'''堆排序:
堆的概念:
    若以一维数组存储一个堆,则堆对应一棵完全二叉树,且所有非叶结点的值
    均不大于(或不小于)其子女的值,根结点(堆顶元素)的值是最小(或最大)的.

堆排序的过程:
    1.初始时把要排序的n个数的序列看作是一棵顺序存储的二叉树(一维数组存储二叉树),
    调整它们的存储序,使之成为一个堆,将堆顶元素输出,得到n个元素中最小的元素;
    2.然后对前面(n-1)个元素重新调整使之成为堆,输出堆顶元素;
    3.重复1,2,直到只有两个节点的堆,并对它们作交换,最后得到有n个节点的有序序列。

稳定性:
    不稳定

时间复杂度:
    nlogn
'''

# list = [9, 8, 7, 6, 5, 4, 3, 2, 1]
list = [50, 80, 10, 40, 20, 70, 30, 60]


# 堆排序,整个过程就是不断地从堆顶移除,调整最大数到堆顶,重复len(list)次
def heap_sort(list):
    size = len(list)
    build_heap(list, size)
    for size_i in range(size)[::-1]:
        list[0], list[size_i] = list[size_i], list[0]   # 将放在堆顶的当前最大的数推出(放在最后一个当前遍历的最后一个位置,并将当前堆中的最后一个数放在堆顶.)
        adjust_heap(list, 0, size_i)   # 注意此时size=i,下一个迭代中整棵树截断了已经排好当前最大数,并且每次都是从堆顶开始进行下一次遍历
    return list

# 创建堆:原始序列的堆,经过所有非叶子节点从后向前的调用adjust(递归方式,注意max的跟踪),保证调整后的堆为"大顶堆"
def build_heap(list, size):
    for none_leaf in range(size // 2)[::-1]:   # size//2 为最后一个非叶子节点的序号
        adjust_heap(list, none_leaf, size)

# 调整堆,使得大小为size_i的树为"大顶堆"
def adjust_heap(list, parent, size):
    lchild = 2 * parent + 1
    rchild = 2 * parent + 2
    if lchild < size:   # 如果当前节点是非叶子节点(还有孩子),才有继续递归调整堆的必要
        max = parent   # max 记录了当前子树(三个节点)中最大的数的序号
        if lchild < size and list[lchild] > list[max]:
            max = lchild
        if rchild < size and list[rchild] > list[max]:
            max = rchild
        if max != parent:
            # 将当前最大数(孩子节点所在位置)和parent节点调换位置,以保证parent节点上的数比孩子节点都大
            list[max], list[parent] = list[parent], list[max]
            # 当前max经过上一步的调换,为上个parent节点的所在的数,如果还有孩子节点则继续adjust
            adjust_heap(list, max, size)


print("排序之后:%s" %heap_sort(list))

posted on 2017-03-04 19:59  会飞的蝸牛  阅读(240)  评论(0编辑  收藏  举报

导航