吃透排序算法之堆化排序
排序算法不仅仅是无序到有序, 其中涉及了数组的遍历处理, 划分的模板运用, 甚至其中还设计到了数组到树的堆化处理. 可以说吃透了排序算法, 可以成为一个合格的算法初学者了.
本系列文章带领读者吃透排序算法, 掌握数组的处理方式, partition
模板, 数组的二叉树形式并进行堆化处理.
吃透排序算法之堆化排序为本系列的堆化排序介绍, 利用数组和树的相互特性来对数组排序, 本文主要涉及:
- 二叉树
- 堆排序
二叉树
二叉树是节点的集合, 通常节点有值和左右的节点. 就像一颗两个叉的树. 二叉树可以用链式存储, 也可以用数组存储. 利用数组下标, 规定对于root
号元素, 其左节点为root*2+1
, 右节点同理为root*2+2
. 二叉树第一个非叶子节点为((len(tree)-1)-1)/2
.
堆排序
堆排序利用的顶堆的性质, 根节点比子树节点的数值大, 就可以保证顶堆的0
号元素为整个数组的最大值, 之后重新对未排序的数组重新堆化即可实现堆排序. 整个过程有点类似遍历排序中的选择排序, 但选择排序是找数组内的最值, 没有有效利用附加的性质, 堆则有着根节点大于叶子节点的性质, 速度快于选择排序.
nums = [1, 3, 2, 5, 4, 6]
def adjust(root, size):
if root*2+1 > size-1:
return
lchild = root*2+1
rchild = root*2+2
maxidx = rchild if rchild < size and nums[rchild] > nums[lchild] else lchild
if nums[maxidx] > nums[root]:
nums[root], nums[maxidx] = nums[maxidx], nums[root]
adjust(maxidx, size)
root, size = int(((len(nums)-1)-1)/2), len(nums)
while root >= 0:
adjust(root, size)
root -= 1
order = len(nums)-1
while order >= 0:
nums[0], nums[order] = nums[order], nums[0]
adjust(0, order-1+1)
order -= 1
print(nums)
小结
本文介绍了二叉树的定义和堆排序的实现, 了解了二叉树数组化存储, 非叶子节点定位, 堆排序类似于选择排序, 相比于选择排序利用了堆的性质, 所以会更快.