python算法(六)堆排序
堆
如上图, 一个堆应该满足所有的子节点都 不大于(不小于)父节点.
当子节点不大于父节点的时候,称为大顶堆
当子节点不小于父节点的时候,称为小顶堆
堆是一个概念上的名词,在实际的程序中,堆是以列表的形式存在的.
因此,如上的堆对应的列表是60 40 32 20 35 45 20 15 10 5 21 25 42 43
堆排序图示
- 首先要将乱序的列表,排列成堆
原始列表: 2 4 8 3 6 1
排列成堆状图:
2
4 8
3 6 1
4 < 6
调整成
2
6 8
3 4 1
2<6<8
调整成
8
6 2
3 4 1
相应列表: 8 6 2 3 4 1 - 将堆的根节点与最后一个元素互换位置
1 6 2 3 4 8
然后去掉最后一个元素
重新按上面的步骤,重新排堆,换位置,去掉元素再排堆
直到最后一上元素
代码实现
from random import shuffle
def big_endian(num_list, start, end):
root = start # 设置根节点
child = 2 * root + 1 # 左子节点
# 循环直到没子节点的元素为止
while child <= end:
# 比较左右两个子节点的大小,以便与父节点比较
if child + 1 <= end and num_list[child] < num_list[child + 1]:
child += 1
# 如果子节点更大,交换父子节点的位置
if num_list[root] < num_list[child]:
num_list[root], num_list[child] = num_list[child], num_list[root]
# 交换好子节点,会破坏下层节点的堆状,要重新调整子节点的堆装
root = child
child = 2 * child + 1
else:
# 如果没有破坏堆状,则继续退出
break
def heap_sort(num_list):
first=len(num_list)//2 - 1 # 从最后一个父节点开始构造大顶堆
for start in range(first, -1, -1):
big_endian(num_list, start, len(num_list)-1)
# 不断去掉根节点,然后构造新的大顶堆 直到最到一个元素
for end in range(len(num_list)-1, 0, -1):
num_list[0], num_list[end] = num_list[end], num_list[0]
big_endian(num_list, 0, end -1)
return num_list
if __name__ == '__main__':
num_list_demo = [x for x in range(10)]
shuffle(num_list_demo)
print(num_list_demo)
heap_sort(num_list_demo)
print(num_list_demo)
转载请注明:XAMPP中文组官网 » python算法教程(六)堆排序