堆排序
"""
堆排序:
堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。
堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
堆排序可以说是一种利用堆的概念来排序的选择排序。
大顶堆:arr
[i
] >= arr
[2i
+1] && arr
[i
] >= arr
[2i
+2] 根节点大于两个子节点的值
小顶堆:arr
[i
] <= arr
[2i
+1] && arr
[i
] <= arr
[2i
+2] 根节点小于两个子节点的值
堆排序的基本思想是:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。
--> 有两个构造堆的过程:一个是初始数组构造成堆(不断从后面插入),另一个是堆顶与末尾元素互换后重新构造堆(从头向下比较)
将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n
-1个元素重新构造成一个堆,这样会得到n个元素的次小值。
如此反复执行,便能得到一个有序序列了
1.首先将待排序的数组构造成一个大根堆,此时,整个数组的最大值就是堆结构的顶端
2.将顶端的数与末尾的数交换,此时,末尾的数为最大值,剩余待排序数组个数为n
-1
3.将剩余的n
-1个数再构造成大根堆,再将顶端数与n
-1位置的数交换,如此反复执行,直到只剩下一个元素为止,便能得到有序数组
"""
# 将初始数组构造成大根堆(通过新插入的数上升)
def
heapInsert(arr
):
"""将待排序数组构造成一个大根堆,每次插入新的数据的时候,都与它的父节点进行比较,
如果比父节点的值大,则进行交换,然后继续与新的父节点进行比较,直到小于等于父节点,或者到达顶端;
如果比父节点小,则插入就可以了
"""
for i
in range(len(arr
)): # 遍历数组
currentIndex
= i # 记录当前索引
# 计算父节点
fatherIdx
= int((currentIndex
- 1) / 2)
# 当前节点与父节点的值进行比较
while arr
[currentIndex
] > arr
[fatherIdx
]: # 当前值比父节点大
# 进行交换
arr
[currentIndex
],arr
[fatherIdx
] = arr
[fatherIdx
],arr
[currentIndex
]
# 更改当前的索引
currentIndex
= fatherIdx
# 重新计算父节点
fatherIdx
= int((currentIndex
- 1) / 2)
# 直到当前节点到达顶端或者比父节点小,插入下一个
# 固定最大值,将剩余的数再次构造成大根堆
,这属于一个循环操作,可以使用递归实现,直到只剩下一个元素结束
def
heapify(arr
,index
,size
):
"""将顶端的最大值与数组末尾的数交换,重新构造大根堆,通过顶端的数下降来重新构造"""
# 计算当前index的左右子节点,index总是从根节点
0开始
left
= 2 * index
+ 1
right
= 2 * index
+ 2
while left
< size
: # 当存在左孩子的时候,可以进行重新构造
# 拿到子节点中较大值的索引
largeIdx
= 0
if arr
[left
] < arr
[right
] and right
< size
: # 右孩子存在并且右孩子大于左孩子,右子节点的索引值不能超过数组长度size(说明右孩子存在)
largeIdx
= right
else: # 没有右孩子或者左孩子值较大
largeIdx
= left
# 如果当前父节点的值比较大孩子节点大,当前父节点,说明只有当前这个父节点的子树发生了变化
if arr
[index
] > arr
[largeIdx
]: # 当父节点已经是最大,说明已经构成大根堆
break
else: # 继续修改当前父节点的子树
# 如果父节点的值比孩子节点小,进行交换
arr
[index
],arr
[largeIdx
] = arr
[largeIdx
],arr
[index
]
# 更改父节点的索引指向
index
= largeIdx
# 继续与新的子节点进行比较
left
= 2 * index
+ 1
right
= 2 * index
+ 2
# 进行堆排序
def
heapSort(arr
):
# 构造大根堆
heapInsert(arr
)
size
= len(arr
)
# 固定最大值,再次构造大根堆
while size
> 1:
arr
[0],arr
[size
-1] = arr
[size
- 1],arr
[0] # 最大值与末尾元素交换
size
= size
- 1 # 元素长度少了最大值
heapify(arr
,0,size
) # 重新构造大根堆
return arr
if __name__
== '__main__':
a
= [1,5,7,4,12,36,48,1,2,4,78,89,6,100]
print(heapSort(a
))