20191209-八大排序之堆排序
1. 堆排序
算法核心思想
堆排序利用堆的特点, 最大堆要求节点的元素都要不小于其孩子,最小堆要求节点元素都不大于其左右孩子,那么处于最大堆的根节点的元素一定是这个堆中的最大值,每次把堆顶元素放置在二叉树的尾部,然后重新建堆这样循环处理,最终就能完成排序。
核心算法逻辑如下:
- 建堆
- 把堆顶的元素和最后一个元素交换,这样,最大的元素就排到了最后面
- 把堆的尺寸缩小 1,并调用 shift_down(0),目的是把新的数组顶端数据调整到相应位置
- 重复上面的1到3步,之后遍历完堆
在堆中,节点i的左子节点是2*i+1,右子节点是2*i+2,故最小值堆满足如下的特点:
- Node(i).value < Node(2*i+1).value
- Node(i).value < Node(2*i+2).value
代码实现
建堆,建堆的过程通过数组的给定数组的下标,建立以给定下标为根的堆,具体过程如下:
def heapify(arr,root_index,arr_length): """给定数组,数组的下标,当前需要建堆的数组长度""" left_index = 2*root_index+1 right_index = 2*root_index+2 max_index = root_index #找到以arr[root_index]为根的堆的与左右子树3个节点中最大值的索引 if left_index<arr_length and arr[left_index]>arr[max_index]: max_index = left_index if right_index<arr_length and arr[right_index]>arr[max_index]: max_index = right_index if max_index!=root_index: arr[max_index],arr[root_index] = arr[root_index],arr[max_index] heapify(arr,max_index,arr_length) def buildheap(arr): """从堆的最后一个有子节点的索引开始建堆,然后逐一给堆添加节点""" for i in range(len(arr)//2,-1,-1): heapify(arr,i,len(arr))
将堆顶的元素与最后一个元素交换,缩短数组的长度再次建堆,重复直至排序完成
def heapSort(arr): arr_length = len(arr) buildheap(arr)#先建堆 for i in range(arr_length): arr[0],arr[arr_length-i-1]= arr[arr_length-i-1],arr[0] heapify(arr,0,arr_length-i-1)#此时堆的结构变化,调整堆结构 return arr
执行解析
heapify(arr,root_index,arr_length)函数实现了一个建堆的过程,一定要从堆的最下层节点开始建堆,如果从堆的最上层开始建堆,则该函数无法保证堆的所有节点满足堆的结构
建立堆后每次取堆顶的元素(arr[0]的位置)放置到第arr_len-i的位置(第一次放置在倒数第一个位置,第二次放置在倒数第二个位置,第n次放置子倒数第n个位置)当最后所有元素放置完成后排序结束。
- 使用使用buildheap函数建立第一个最大堆
- 使用heapify调整堆结构保证
- 使用heapsort实现堆排序的交换
时间复杂度:O(N*logN)。
总结
堆排序的时间复杂度为O(n*logn),堆排序是使用完全二叉树的特点来实现的一种排序方式
相关推荐
hanyujianke 2020-01-04
shawsun 2019-12-15
ding0 2019-06-27
tkernel 2018-09-10
HTML学堂码匠 2018-05-11
ELEMENTS爱乐小超 2020-07-04
sunjunior 2020-05-10
shenwenjie 2020-05-03
shawsun 2020-04-17
ustbfym 2020-04-09
rein0 2020-04-08
shawsun 2020-03-28
Happyunlimited 2019-12-02
燕哥带你学算法 2019-11-19
qscool 2019-11-08
qscool 2019-10-28
nimeijian 2019-10-21