__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))