• 算法学习:堆排序


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

    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)

  • 相关阅读:
    10. 王道考研-树与二叉树
    Shell基础论证实例
    关系型数据库与非关系型数据库区别
    中高级测试工程师面试题
    idea中cucumber环境搭建
    Java开发中对Redis的基本操作总结
    TestNG 单元测试框架(针对于testNG.xml配置)
    jmeter(四十五)常用Beanshell脚本
    Jmeter(二十一)_脚本两种参数化
    Jmeter(十五)_上传与下载
  • 原文地址:https://www.cnblogs.com/hqq2019-10/p/14085964.html
Copyright © 2020-2023  润新知