优化堆的堆结构

时间:2016-08-18 10:50:10

标签: java algorithm performance heap heapsort

我正在使用堆实现heapsort。为此,插入要排序的每个值。插入方法调用heapifyUp()(也就是siftUp),这意味着每次插入另一个值时都会调用heapifyUp。这是最有效的方式吗?

另一个想法是插入所有元素,然后调用heapifyUp。我猜每个人都必须调用heapifyUp吗?这样做会更好吗?

1 个答案:

答案 0 :(得分:2)

插入每个元素将在O(n log n)时间内构建堆。如果将所有元素添加到数组然后重复调用heapifyUp()

,则同样如此

Floyd's Algorithm在O(n)时间内自下而上构建堆。这个想法是你以任何顺序排列一个数组,从中间开始,将每个项目向下筛选到适当的位置。算法是:

for i = array.length/2 downto 0
{
    siftDown(i)
}

你从中间开始,因为数组中的最后一个长度/ 2个项目是叶子。他们不能被削减。通过从中间向上工作,您可以减少必须移动的项目数量。

差异的例子

以下示例将7个项目的数组转换为堆,显示完成工作量的差异。

heapifyUp()方法

[7,5,6,1,2,3,4]  (starting state)

从最后开始,冒泡项目。

将4移动到适当的位置

[7,5,4,1,2,3,6]
[4,5,7,1,2,3,6]

将3移至其位置

[4,5,3,1,2,7,6]
[3,5,4,1,2,7,6]

将2移至其位置

[3,2,4,1,5,7,6]
[2,3,4,1,5,7,6]

将1移至其位置

[2,1,4,3,5,7,6]
[1,2,4,3,5,7,6]

堆现在正常。它需要8次交换,你仍然需要检查4,2和1。

弗洛伊德的算法

[7,5,6,1,2,3,4]  (starting state)

从中途开始并向下筛选。在基于0的7项数组中,中间点为3。

将1移至其位置

[7,5,6,1,2,3,4]  (no change. Remember, we're sifting down)

将6移至其位置

[7,5,3,1,2,6,4]

将5移至其位置

[7,1,3,5,2,6,4]
[7,1,3,4,2,6,5]

将7移至其位置

[1,7,3,5,2,6,4]
[1,2,3,5,7,6,4]

我们已经完成了。它需要进行5次互换,没有别的可以检查。