我尝试使用谷歌搜索和维基这些问题,但似乎无法找到具体的答案。我发现的大部分内容都使用了带有主定理的证明,但我希望用简单的英语来更直观地记住这些东西。我也不在学校,这些问题都是面试的。
MEMORY:
在内存使用方面确定big-o到底意味着什么?例如,当你必须存储所有n个项目时,为什么heapsort被认为运行O(1)内存?是因为你只为堆创建一个结构吗?或者是因为你知道它的大小,所以你可以在堆栈上创建它,这总是恒定的内存使用?
SPEED:
如果在O(1)中完成添加元素但是在O(logn)中完成渗透,如何在O(n)时间内完成堆的创建?这不意味着你在O(1)处进行n次插入使其成为O(n)并且在每次插入之后渗透为O(logn)。所以总共O(n)* O(logn)= O(nlogn)。我还注意到堆排序的大多数实现使用heapify函数而不是渗透来创建堆?由于heapify在O(logn)处进行n比较,即O(nlogn),并且在O(1)处有n个插入,我们将得到O(n)+ O(nlogn)= O(nlogn)?第一种方法不会比第二种方法产生更好的性能吗?
我在上面假设了这一点,但是进行n次O(1)操作会导致O(n)时间吗?或者n * O(1)= O(1)?
答案 0 :(得分:0)
所以我发现了一些有关从维基百科构建二进制堆的有用信息:http://en.wikipedia.org/wiki/Binary_heap#Building_a_heap。
我认为我的主要困惑是如何“插入”堆是O(1)和O(logn),即使第一个不应该被称为插入,也许只是一个构建步骤或其他东西。因此,在您已经创建堆之后,您将不再使用heapify,而是使用O(logn)插入方法。
在保持堆属性的同时迭代添加项目的方法在O(nlogn)中运行并在不考虑堆属性的情况下创建堆,然后堆积,实际上在O(n)中运行,其原因不是很直观并要求提供证明,所以我错了。
在每个方法都有一个尊重堆属性的堆之后,获取有序项的删除步骤与O(nlogn)的成本相同。
所以最后你的构建堆方法有O(1)+ O(n)+ O(nlogn)= O(nlogn),而O(nlogn)+ O(nlogn)= O(nlogn)用于插入方法。显然第一个是优选的,特别是对于小n。