算法之堆排序

基本认识

  1. 定义:堆可以定义为一颗二叉树,树的每一个节点包含一个键,且这棵二叉树是完全二叉树,即除了最后一层,树的每一层都是满的,最后一层右边可能有缺位。



    由于结点左侧缺位,非堆
  2. 大顶堆:父节点的键值要大于或者等于子女结点的键值。
  3. 小顶堆:父节点的键值要小于或者等于子女结点的键值。
  4. 补充:用数组实现堆,堆并不是实际存在,认为定义的一个逻辑 ;结点n的左孩子为2n + 1,右孩子为2n + 2,结点m的父节点为(m - 1)/2


大顶堆的实现堆排序

  1. 构建大顶堆:遍历待排数组,判断每个元素与父节点元素的大小,如果孩子结点元素比父结点元素大,交换两个元素的位置,直到孩子结点元素小于等于父结点元素大小。
    步骤一:结点元素位置为 i,所以元素开始比较位置index = i
    步骤二:判断 index 位置(孩子元素)与 (index - 1)/2 位置(父元素)大小
    a. 如果arr[index] > arr[(index-1)/2],交换index位置与(index-1)/2位置元素, index = (index-1)/2,执行步骤二
    b. 如果arr[index] <= arr[(index-1)/2],执行步骤三
    步骤三:i += 1,如果 i <= len(arr),执行步骤二,否则,结束算法

  2. 获取有序数组
    步骤一:堆顶位置为 l,堆最后一个元素位置 r
    步骤二:将 r 位置与 l 位置元素(堆顶位置元素,也即是最大元素)交换, r -= 1(解析:将r位置与对顶位置元素交换,那么对顶位置就会在待排数组最后位置上,即待排数组中最大元素将会被换到待排元素最后位置上,所以大于等于r位置上的元素都有序),此时,大顶堆结构被破坏(因为堆顶位置非最大元素),待调整结点位置为 index = l
    步骤三:对index结点进行调整
    a. 左孩子结点位置为 left = index *2 + 1,右孩子结点位置为 left + 1
    b. left <= r:如果右孩子不存在(left +1 > size)或者左孩子元素比有孩子元素大,maxIndex = left,否则maxIndex = left + 1
    c. 如果arr[index] >= arr[maxIndex],交换两个位置元素,index = maxIndex,执行步骤三,否则结束调整
    d. left > r,待调整结点无孩子结点,结束调整
    步骤四:如果 r >= l,执行步骤二, 否则结束算法

图解过程

  1. 待排数组

2.构建大顶堆
  1. 获取有序数组

代码实现

def headSort(arr):
    if(len(arr) <= 1):
        return
    for i in range(len(arr)):
        headInsert(arr, i)
    r = len(arr) - 1
    while(r >= 1):
        arr[0], arr[r] = arr[r], arr[0]
        r -= 1
        heapify(arr, 0, r)

def headInsert(arr, index):
    index_half = int((index - 1)/2)
    while(arr[index] > arr[index_half]):
        arr[index], arr[index_half] = arr[index_half], arr[index]
        index = index_half
        index_half = int((index - 1)/2)

def heapify(arr, l, r):
    maxIndex = l
    index = l
    left = index * 2 + 1
    while(left <= r):
        maxIndex = left if (left + 1 > r) or arr[left] > arr[left + 1] else left + 1 # 判断最大值在左字树还是右子树
        maxIndex = maxIndex if arr[maxIndex] > arr[index] else index
        if(maxIndex == index):
            break
        arr[index], arr[maxIndex] = arr[maxIndex], arr[index]
        index = maxIndex
        left = index * 2 + 1
  
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 详细代码请参考Algorithm。参考代码比文字好理解。 堆排序是时间复杂度为O(N*lgN)的排序方法。是指利用...
    一个人在路上走下去阅读 1,530评论 1 2
  • 时间复杂度:O(Nlog(N))额外空间复杂度:O(1)是否可实现稳定性:否 思路: 把数组逻辑上看成一个二叉树,...
    一凡呀阅读 665评论 0 0
  • 堆排序 堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O...
    4e70992f13e7阅读 1,133评论 0 0
  • 堆排序是指利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构(通常堆是通过一维数组来实现的),并...
    BEYOND黄阅读 202评论 0 2
  • 完全二叉树的基本概念 可能你会疑问,为什么我们明明讲的是堆排序,怎么又扯上了二叉树的概念了,答案就是,我们这里的堆...
    再见远洋阅读 1,104评论 0 7