zoukankan      html  css  js  c++  java
  • 算法学习:堆排序

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

    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)

  • 相关阅读:
    浅谈观察者设计模式
    关于如何成为专家(1)
    微信小程序 PHP后端form表单提交实例详解
    mysql中的union和order by、limit
    SQL的各种连接(cross join、inner join、full join)的用法理解
    mysql数据库创建、删除数据库
    PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP 未声明(在此函数内第一次使用) 规格严格
    TroubleshootingGuide for JavaTM SE 6withHotSpot TM VM (翻译附录未完待续) 规格严格
    关闭URLClassLoader打开的jar包 规格严格
    两个长度分析【POST|GET】 规格严格
  • 原文地址:https://www.cnblogs.com/hqq2019-10/p/14085964.html
Copyright © 2011-2022 走看看