ustbfym 2019-12-09
堆排序利用堆的特点, 最大堆要求节点的元素都要不小于其孩子,最小堆要求节点元素都不大于其左右孩子,那么处于最大堆的根节点的元素一定是这个堆中的最大值,每次把堆顶元素放置在二叉树的尾部,然后重新建堆这样循环处理,最终就能完成排序。
核心算法逻辑如下:
在堆中,节点i的左子节点是2*i+1,右子节点是2*i+2,故最小值堆满足如下的特点:
建堆,建堆的过程通过数组的给定数组的下标,建立以给定下标为根的堆,具体过程如下:
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个位置)当最后所有元素放置完成后排序结束。
时间复杂度:O(N*logN)。
堆排序的时间复杂度为O(n*logn),堆排序是使用完全二叉树的特点来实现的一种排序方式