使用heapify vs heappush创建堆。哪一个更快?

时间:2017-02-12 11:03:07

标签: python performance time-complexity heap

问题

我必须创建一个存储距离的优先级队列。为了构建堆,我正在考虑以下两种可能性:

heapify()

哪一个更快?

推理

根据文档heappush()以线性时间运行,我猜测heapify()在O(log n)时间内运行。因此,每种方式的运行时间为:

  • A:O(2n)= O(n)
  • B:O(n log n)

然而,对我而言,A比B快,这是违反直觉的。我错过了什么?它真的比B快吗?

**编辑

我一直在测试不同的输入和不同大小的阵列,我仍然不确定哪一个更快。

在阅读了Elisha的评论链接后,我理解heappush()在线性时间内的运行方式。但是,我仍然不知道使用heappush()是否会更快,具体取决于输入。

我的意思是,heapify()最坏情况运行时间为O(log n),但平均值可能会更小,具体取决于输入。它的最佳情况运行时间实际上是O(1)。另一方面,heappush()最佳情况运行时间为O(n),并且必须在填充数组后调用,这也需要O(n)。这是O(2n)的最佳情况。

所以heapify()可以像线性一样快或者比O(n log n)慢,而2n在任何情况下都需要heapify()时间。如果我们看一下最糟糕的情况,<?php function filter_where( $where = '' ) { $where .= " AND post_date > '" . date('Y-m-d', strtotime('-30 days')) . "'"; return $where; } add_filter( 'posts_where', 'filter_where' ); $the_query = new WP_Query(array( 'posts_per_page' => 3, 'cat' => 2, 'orderby' => 'comment_count date', 'order'=> 'DESC' )); remove_filter( 'posts_where', 'filter_where' ); ?> <?php while ( $the_query->have_posts() ) : $the_query->the_post(); echo get_the_title(); // and rest of content endwhile; wp_reset_postdata(); ?> 会更好。但是一般情况呢?

我们甚至能确定一个人比其他人更快吗?

1 个答案:

答案 0 :(得分:0)

是的,我们可以确定一个比另一个更快。

heap.push从下到上构建堆。每个项目都被添加到数组的末尾,然后“冒出来”#34;到了正确的位置。如果您正在构建一个最小堆,并且您以相反的顺序显示了这些项,那么您插入的每个项都需要log(n)(n是堆的当前大小)比较。因此,通过插入构建堆的最坏情况是O(n log n)。

想象一下从空堆开始并以相反的顺序添加127个项目(即127,126,125,124等)。每个新项目都小于所有其他项目,因此每个项目都需要最大数量的交换从最后一个位置到顶部。添加的第一个项目进行零交换。接下来的两个项目分别进行一次交换。接下来的四个项目分别进行两次交换。八个项目进行三次交换。 16个项目进行四次交换。 32个项目进行5次交换,64个项目进行6次交换。它可以解决:

0 + 2*1 + 4*2 + 8*3 + 16*4 + 32*5 + 64*6
0 + 2 + 8 + 24 + 64 + 160 + 384 = 642 swaps

build-heap最坏情况是n个交换。考虑127个项目的相同数组。叶级别包含64个节点。 build-heap从中间点开始向后移动,根据需要向下移动。倒数第二级有32个节点,最坏的情况是向下移动一个级别。下一级别有16个节点,不能向下移动两个以上的级别。如果你把它添加起来,你会得到:

64*0 + 32*1 + 16*2 + 8*3 + 4*4 + 2*5 + 1*6
0 + 32 + 32 + 24 + 16 + 10 + 6 = 120 swaps

这是build-heap的绝对最坏情况。它是O(n)。

如果你在一百万个项目的数组上分析这两个算法,你会发现运行时间差别很大,build-heap要快得多。