我正在使用堆实现heapsort。为此,插入要排序的每个值。插入方法调用heapifyUp()
(也就是siftUp),这意味着每次插入另一个值时都会调用heapifyUp。这是最有效的方式吗?
另一个想法是插入所有元素,然后调用heapifyUp。我猜每个人都必须调用heapifyUp吗?这样做会更好吗?
答案 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次互换,没有别的可以检查。