排序算法:heap sort(含heap介绍,python)

heap介绍

binary heap可以被看成是一种接近完成的binary tree。可以分为max-heap和min-heap,max-heap的parent要比children大,min-heap相反。

通常用array A构成的heap中,有两个基本的特性:1. A.length,给出了阵列中的元素个数。2. A.heap-size,给出阵列中在heap中的元素。

这两者的区别是,A.heap-size中的才是在heap里的,A.length的长度可能还包含了其他的很多元素。

这个可以在之后的代码中可以看见。比如有一个list有8个元素,但只有前7个元素在heap里,满足heap的特性,则A.length=8, A.heap-size=7。

heap与array的示意图如下。

一些特性:

  1. 对于每个节点,要想知道其父与子,有以下关系:

    PARENT(i)

    return[i/2]

    LEFT(i)

    return[2i]

    RIGHT(i)

    return(2i+1)

    注意,这里的i是从1开始的,在实际写代码是,一般的list序列都是从0开始,要注意两者之间的不同。这个在之后的代码中会有体现。

  2. 要把一个A[1...n]转化成heap,在A([n/2]+1...n)中的所有元素都是heap的叶子。
  3. 保持max-heap特性的操作

这个函数结合build Max heap 是保持整个heap特性的关键。下面讨论具体的实现方法

创建一个max heap

首先要实现从某一个节点开始的max heap

算法如下:

此过程的时间复杂度为o(logn)

在此基础上,建立一个max heap的算法如下:

此过程的时间复杂度为o(nlogn)

heap的priority-queue运算

prority-queue是一种数据结构,它的每一个元素都有一个key值,主要有以下几种运算,其使用heap实现的算法如下。

插入一个元素

此过程的时间复杂度为o(logn)

增加一个元素的值

此过程的时间复杂度为o(logn)

提取最大元素

此过程的时间复杂度为o(logn)

从中可以看到heap的一个重要特性,就是它可以将所有priority-queue运算在时间复杂度lgn内完成。

heap的应用:heap sort

整个过程分为

  1. 建立heap
  2. 提取最大值
  3. 放在序列最后
  4. 重复指导排序完成

    具体算法如下:

实现

#heap
class heap(object):
    def __init__(self,A):
        """
        A is a list
        """
        # self.list = [0]
        self.list = A[:]
        # self.list.insert(0,0)
        self.heapsize = len(A)
        # self.ismaxheap = False
        self.build_max_heap()

    def __str__(self):
        return str(self.list)

    def left(self, i):
        return 2*(i+1)-1
    def right(self, i):
        return 2*(i+1)
    def parent(self, i):
        return (i-1)/2

    def insert(self, key):
        """
        run time o(logn)
        """
        self.heapsize += 1
        self.list.append(-float("inf"))
        self.increase_key(self.heapsize-1,key)

    def increase_key(self,i,key):
        """
        run time o(logn)
        """
        if key < self.list[i]:
            raise ValueError("new key is smaller than current key")
        self.list[i] = key
        while i>0 and self.list[self.parent(i)] < self.list[i]:
            # print("i1="+str(i))
            temp = self.list[i]
            self.list[i] = self.list[self.parent(i)]
            self.list[self.parent(i)] = temp
            i = self.parent(i)
            # print("i2="+str(i))

    def max_heapify(self, i):
        """
        run time: o(logn)
        the key to maintain the max-heap property
        """
        l = self.left(i)
        r = self.right(i)
        # i_m = i
        # largest = 0
        # print("l="+str(l)+" r="+str(r))
        # print(self.heapsize)
        largest = i
        if l < self.heapsize:
            if self.list[l] > self.list[i]:
                largest = l
        # print("r="+str(r)+" largest="+str(largest))
        if r < self.heapsize:
            if self.list[r] > self.list[largest]:
                largest = r
        # print("largest="+str(largest))
        if largest != i:
            temp = self.list[i]
            self.list[i] = self.list[largest]
            self.list[largest] = temp
            self.max_heapify(largest)

    def build_max_heap(self):
        """
        run time: o(nlogn)
        """
        # print(self.heapsize//2)
        for i in range(self.heapsize//2-1,-1,-1):
            # print(i)
            self.max_heapify(i)
        # self.ismaxheap = True

    def extract_max(self):
        """
        build a maxheap and return the max value of it(the first element)
        also pop the first element out of the heap
        run time o(logn)
        """
        if self.heapsize < 1:
            raise ValueError("heap underflow")
        # if self.ismaxheap == False:
            # self.build_max_heap()
        maxele = self.list[0]
        self.list[0] = self.list[self.heapsize-1]
        self.list[self.heapsize-1] = maxele
        self.heapsize -= 1
        self.max_heapify(0)
        return maxele

    def heap_sort(self):
        """
        using recurrence to impelete, can also use for loop
        """
        if self.heapsize == 1:
            return self.list
        self.build_max_heap()
        temp = self.list[0]
        self.list[0] = self.list[self.heapsize-1]
        self.list[self.heapsize-1] = temp
        self.heapsize -= 1
        self.heap_sort()

A = [3,4,5,7,1,4,9]
heap1 = heap(A)
print(heap1)
heap1.insert(2)
print(heap1)
print(heap1.heapsize)
maxele = heap1.extract_max()
print(maxele)
print(heap1)
print(heap1.heapsize)
heap1.increase_key(3,10)
print(heap1)
print(heap1.heapsize)
heap1.heap_sort()
print(heap1)
print(heap1.heapsize)

原文地址:https://www.cnblogs.com/litingyu/p/9212413.html

时间: 2024-10-29 04:51:36

排序算法:heap sort(含heap介绍,python)的相关文章

经典排序算法 - Flash Sort

经典排序算法 - Flash Sort FlashSort依然类似桶排,主要改进了对要使用的桶的预测,或者说,减少了无用桶的数量从而节省了空间,例如 待排数字[ 6 2 4 1 5 9 100 ]桶排需要100个桶,而flash sort则由于可以预测桶则只需要7个桶 即待排数组长度个桶,如何预测将要使用的桶有这么一个公式 该排序有前置条件,需要知道待排数组的区间和待排数组的长度, 例如已知待排数组[ 6 2 4 1 5 9 ]的长度为6,最大值9,最小值1,这三个是已知条件,如果无法知道这三个

经典排序算法 - Strand Sort

经典排序算法 - Strand Sort Strand sort是思路是这样的,它首先需要一个空的数组用来存放最终的输出结果,给它取个名字叫"有序数组" 然后每次遍历待排数组,得到一个"子有序数组",然后将"子有序数组"与"有序数组"合并排序 重复上述操作直到待排数组为空结束 看例子吧 待排数组[ 6 2 4 1 5 9 ] 第一趟遍历得到"子有序数组"[ 6 9],并将其归并排序到有序数组里 待排数组[

经典排序算法 - Proxmap Sort

经典排序算法 - Proxmap Sort 这个排序是桶排序和基数排序的改进,理解了前两者,这个排序很容易理解 先回忆下桶排序是怎么回事,它与桶的区别在于入桶规则,桶排序里是1入1号桶,2入2号桶 这个排序把数字分区了,然后给出一个所谓的键,例如它规定0-9都入0号桶 10-19都入1号桶,这样桶覆盖的范围将增大10倍,这在某种情况下是很有用的 有了桶排的基础后,再看下边两张图就什么都明白了,不再分解过程了 图1 图2

《算法导论》读书笔记之排序算法—Merge Sort 归并排序算法

自从打ACM以来也算是用归并排序了好久,现在就写一篇博客来介绍一下这个算法吧 :) 图片来自维基百科,显示了完整的归并排序过程.例如数组{38, 27, 43, 3, 9, 82, 10}. 在算法导论讲分治算法一章的时候提到了归并排序.首先,归并排序是一个分治算法. 归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表, 即把待排序序列分为若干个有序的子序列,再把有序的子序列合并为整体有序序列. merg() 函数是用来合并两个已有序的数组.  是整个算法的关键. 那么归并

Python实现各种排序算法的代码示例总结

Python实现各种排序算法的代码示例总结 作者:Donald Knuth 字体:[增加 减小] 类型:转载 时间:2015-12-11我要评论 这篇文章主要介绍了Python实现各种排序算法的代码示例总结,其实Python是非常好的算法入门学习时的配套高级语言,需要的朋友可以参考下 在Python实践中,我们往往遇到排序问题,比如在对搜索结果打分的排序(没有排序就没有Google等搜索引擎的存在),当然,这样的例子数不胜数.<数据结构>也会花大量篇幅讲解排序.之前一段时间,由于需要,我复习了

经典排序算法 - 圈排序Cycle Sort

经典排序算法 - Cycle Sort Cycle sort的思想与计数排序太像了,理解了基数排序再看这个会有很大的帮助, 圈排序与计数排序的区别在于圈排序只给那些需要计数的数字计数,先看完文章吧,看完再回来理解这一句话 所谓的圈的定义,我只能想到用例子来说明,实在不好描述 待排数组[ 6 2 4 1 5 9 ] 排完序后[ 1 2 4 5 6 9 ] 数组索引[ 0 1 2 3 4 5 ] 第一部分 第一步,我们现在来观察待排数组和排完后的结果,以及待排数组的索引,可以发现 排完序后的6应该出

经典排序算法

经典排序算法(via  kkun) 经典排序算法,以下文章参考了大量网上的资料,大部分都给出了出处 这一系列重点在理解,所以例子什么的都是最简单的情况,难免失误之处,多指教 大多数排序算法都给出了每一步的状态,以方便初学者更容易理解,通俗易懂,部分难以理解的排序算法则给出了大量的图示,也算是一个特色吧 经典排序算法 - 快速排序Quick sort 经典排序算法 - 桶排序Bucket sort 经典排序算法 -  插入排序Insertion sort 经典排序算法 - 基数排序Radix so

STL笔记(6)标准库:标准库中的排序算法

STL笔记(6)标准库:标准库中的排序算法 标准库:标准库中的排序算法The Standard Librarian: Sorting in the Standard Library Matthew Austern http://www.cuj.com/experts/1908/austern.htm?topic=experts 用泛型算法进行排序    C++标准24章有一个小节叫“Sorting and related operations”.它包含了很多对已序区间进行的操作,和三个排序用泛型

【转】经典排序算法

地址:http://www.cnblogs.com/kkun/archive/2011/11/23/2260312.html 大多数排序算法都给出了每一步的状态,以方便初学者更容易理解,通俗易懂,部分难以理解的排序算法则给出了大量的图示,也算是一个特色吧 经典排序算法 - 快速排序Quick sort 经典排序算法 - 桶排序Bucket sort 经典排序算法 -  插入排序Insertion sort 经典排序算法 - 基数排序Radix sort 经典排序算法 - 鸽巢排序Pigeonho

经典排序算法【转】

转自 还有多少青春可以挥霍 经典排序算法 - 快速排序Quick sort 经典排序算法 - 桶排序Bucket sort 经典排序算法 -  插入排序Insertion sort 经典排序算法 - 基数排序Radix sort 经典排序算法 - 鸽巢排序Pigeonhole sort 经典排序算法 - 归并排序Merge sort 经典排序算法 - 冒泡排序Bubble sort 经典排序算法 - 选择排序Selection sort 经典排序算法 - 鸡尾酒排序Cocktail sort 经