算法学习:堆排序

一、关于二叉树和堆的基本概念

1、二叉树

每个节点,最多有2个子树的数结构。
左右子树,也是最多有2个子节点。

2、满二叉树
除最后一层外,每个节点都有2个子节点。
 
3、完全二叉树
存在的节点,和满二叉树的节点完全对应。
 
4、堆:
Max Heap:最大的元素永远在根节点
任一非终端节点数据均不小于其左、右孩子节点。
 
Min Heap: 最小的元素永远在根节点
任一非终端节点数据均不大于其左、右孩子节点。
 
5、堆的特点:
i 表示索引,用公式找到索引所在节点的父节点和左右孩子节点的索引。
parent = (i-1)//2
c1 = 2*i+1
c2 = 2*i+2
 
二、堆排序的核心思想
以Max Heap 为例:
  第一步:建堆,保证最大元素是堆顶
  第二步:把堆顶元素和最后一个元素位置交换
  第三步:调整堆结构,使堆满足 Max Heap ,调整的时候不再考虑最后一个位置元素
  第四步:再次将堆顶元素和调整后堆的最后一个元素位置交换
  第五步:调整堆结构
  第六步:循环
 
考虑实现过程:
 1.如何让数组满足堆的定义:建堆
构建堆的过程:
  1)从堆的最后一个非叶子节点开始,进行调整
    对于长度为n的堆,确定最后一个非叶子节点的位置:n//2-1
    调整过程:在最后一个非叶子节点 的左右子节点中,找到最大的元素,交换位置
  2)找到倒数第二个非叶子节点,不满足Max需要调整,满足则不调整
  3)一直找到最后一个非叶子节点进行调整,最后满足了Max Heap的条件
堆顶元素和最后一个元素,交换。
交换后破坏了原有堆的结构。
然后缩小堆的规模,继续调整成Max Heap。
 
2. 调整完以后,继续交换
 
三、代码
#调整堆结果
def heapify(arr,action_node_index,length):
    '''
    arr:要传入的数组
    action_node_index:待调整的堆的节点的索引
    length :堆的规模
    '''
    left_child_index = 2*action_node_index+1
    right_child_index = 2*action_node_index+2
    max_value_index = action_node_index
    #分别和左右子节点比较,找到最大的值对应的index
    #在查找的堆的范围内
    if left_child_index<length and arr[left_child_index]>arr[max_value_index]:
        max_value_index = left_child_index
    if right_child_index<length and arr[right_child_index]>arr[max_value_index]:
        max_value_index = right_child_index
    #如果最大值的索引发生了变化,交换位置
    if max_value_index!=action_node_index:
        arr[max_value_index],arr[action_node_index]=arr[action_node_index],arr[max_value_index]
        #因为位置的交换,可能导致交换后的堆不满足堆的结构
        #继续调整基于该节点为根的堆结构
        heapify(arr,max_value_index,length)


#建堆:从最后一个非叶子节点
def buildheapify(arr):
    for i in range(len(arr)//2-1,-1,-1):#左必右开,到0索引结束
        heapify(arr,i,len(arr))

#堆排序
def heapifySort(arr):
    length = len(arr)
    buildheapify(arr)
    for i in range(length):
        #做交换
        arr[0],arr[length-i-1]=arr[length-i-1],arr[0]
        #调整堆
        heapify(arr,0,length-1-i)
    return arr

arr = [-111,12,0,-6,12,88,34,8,-3]
print(heapifySort(arr))
#结果
[-111, -6, -3, 0, 8, 12, 12, 34, 88]

2、时间复杂度:O(nlogn)

原文地址:https://www.cnblogs.com/hqq2019-10/p/14085964.html