📅  最后修改于: 2020-10-29 01:23:50             🧑  作者: Mango
堆排序与选择排序完全相同,在选择排序中,我们找到最大元素并将其放在最后。它基于比较排序算法,该算法适用于二进制堆数据结构。这是高效排序算法的最佳示例。
堆排序是一种有效且流行的排序算法。堆排序的概念是从列表的堆部分“消除”元素,并将其插入到列表的排序部分。在学习有关堆排序算法的更多信息之前,让我们讨论堆数据结构。
它是就地算法,这意味着使用固定数量的内存来存储排序列表,或者内存大小不依赖于初始列表的大小。
例如-我们不需要额外的内存堆栈来存储排序后的数组,也不需要递归调用堆栈。堆排序算法通常使用第二个数组对固定值进行排序。此过程快速,简单,自然且易于实施。
另一方面,堆排序是不稳定的,这意味着它不会保持具有相等值的元素的比较顺序。它可以快速对原始类型(例如整数和字符排序,但是它对复杂的类型和对象存在问题。
让我们通过以下示例了解它-
我们有一个具有年龄和名称属性的自定义班级“学生”,并且该班级中的多个对象(包括一个名为“托马斯”,年龄为“ 20″和“彼得”的学生)以相同的顺序出现。
如果我们按年龄对人群进行排序,则不能保证在排序的数组中“托马斯”出现在“彼得”之前。可以定义顺序,但不能保证。
堆数据结构是一个完整的二叉树,可实现堆属性。也称为二进制堆。
完整的二叉树满足以下属性。
正如我们在堆的上图中所看到的,但它没有排序。我们将不深入研究本文,因为我们的重点是解释堆排序算法,而不是堆。在堆排序中,第二个最小的元素始终是第一个元素。
堆树可以是两种类型-最小堆和最大树。最小堆保留最大元素的记录。最大堆跟踪最大的元素。堆主要支持以下操作-delete_minimum(),get_minimum()和add()。
堆中的第一个元素可以在还原后删除。这需要O(log N)时间,因此非常有效。
Python提供了用于使用堆排序对元素进行排序的内置函数。功能如下。
考虑下面的堆排序示例。
范例-
from heapq import heappop, heappush
def heapsort(list1):
heap = []
for ele in list1:
heappush(heap, ele)
sort = []
# the elements are lift in the heap
while heap:
sort.append(heappop(heap))
return sort
list1 = [27, 21, 55, 15, 60, 4, 11, 17, 2, 87]
print(heapsort(list1))
输出:
[2, 4, 11, 15, 17, 21, 27, 55, 60, 87]
说明
在上面的代码中,我们导入了由heappop()和heappush()方法组成的heapq模块。我们创建了Heapsort Heapsort()方法,该方法将list1作为参数。一个for循环迭代list1并将元素推入空堆。我们使用了while循环和sorted元素添加到空排序中。
我们调用了Heapsort Heapsort()函数并传递了一个列表。它返回排序列表。
堆排序对于预定义的数据类型很有用,但是处理用户定义的数据类型(例如类对象)则更为复杂。我们将在本节中对自定义对象进行排序。
如我们所见,我们的实现取决于内置方法。 Python提供了以下方法。
让我们了解自定义对象的以下实现。
范例-
from heapq import heappop, heappush
class Car:
def __init__(self, model, year):
self.model = model
self.year = year
def __str__(self):
return str.format("Model Name: {}, Year: {}", self.model, self.year)
def __lt__(self, other):
return self.year < other.year
def __gt__(self, other):
return other.__lt__(self)
def __eq__(self, other):
return self.year == other.year
def __ne__(self, other):
return not self.__eq__(other)
def heapsort(list1):
heap = []
for element in list1:
heappush(heap, element)
ordered = []
while heap:
ordered.append(heappop(heap))
return ordered
car1 = Car("Renault", 2001)
car2 = Car("Bentley", 2005)
car3 = Car("Kia", 2014)
car4 = Car("Maruti Suzuki", 1999);
car5 = Car("Nano", 2012)
list1 = [car1, car2, car3, car4, car5]
for c in Heapsort Heapsort (list1):
print(c)
输出:
Model Name: Maruti Suzuki, Year: 1999
Model Name: Renault, Year: 2001
Model Name: Bentley, Year: 2005
Model Name: Nano, Year: 2012
Model Name: Kia, Year: 2014
我们已按年份对对象进行了排序。
流行的快速排序算法之一也非常有效,但是由于其可靠性,合法使用堆排序。就时间复杂度而言,堆排序的主要好处是O(nlogn)上限。
在平均情况和最坏情况下,堆排序算法都需要O(nlogn)时间,而在平均情况下,快速排序要快20%。
在可预测的情况下,快速排序算法会变慢。由于可以很容易地触发犯规O(n2),因此存在快速违反安全性的可能性。
现在,我们将合并排序与堆排序花费的时间进行比较。
合并排序非常稳定并且可以直观地并行化,而堆排序则没有这种优势。
此外,合并排序在大多数情况下比堆排序要快,因为它们具有相同的时间复杂度。
相反,HeapsortHeapsort可以比Marge sort更快地就地实现。
Heapsort并不那么流行且速度更快,但是它比其他任何排序算法都更具可预测性。当优先考虑内存和安全性时,首选此算法。
可以使用Python快速实现。我们需要将元素插入堆中并取出。