睡眠排序的时间复杂度是多少?


69

给定这种排序算法,您如何表达其时间复杂度?

最初显示在这里 (部分存档)

#!/bin/bash
function f() {
sleep "$1"
echo "$1"
}
while [ -n "$1" ]
do
    f "$1" &
    shift
done
wait

example usage:
./sleepsort.bash 5 3 6 3 6 3 1 4 7

8
我认为这是一个与现实世界无关的问题
justinhj 2011年

27
绝对是一个很好的学术问题。如果它像我所做的那样激发思想,那么它一定具有价值。
迪克·切斯特伍德2011年

1
我希望我可以编辑我的评论以阅读“一个有趣的问题”,哎呀
justinhj 2011年

Answers:


35

O(max(input)+n)

由于大多数排序算法都与数据无关,因此很难表达复杂性。它们的时间取决于数据量,而不是数据本身。

FWIW,如指出这里,这不是对数据进行排序可靠的算法。


3
我认为需要输入的数量为O(max(input)+ n)。如果遍历所有输入所花的时间比处理最大输入所花的时间长,那么O(max(input))将是不正确的,不是吗?
yarian 2011年

您可以通过规范化数据来降低复杂性。将所有输入除以max(input)。
键盘手

5
这给您的挂钟时间带来了很大的麻烦(尽管应该O(n log(n))考虑调度程序的工作)。但是,与大多数排序算法不同,该算法使CPU空闲了一段时间,因此,CPU时间的复杂性是O(n)要迭代并启动睡眠线程/进程,再加O(n log n)上调度程序中的CPU时间来管理下一个队列。唤醒。也就是说,O(n log n)CPU时间是吞吐量成本,而O(max(input) + n log (n))挂钟时间是延迟成本。
彼得·科德斯

24

似乎没有人解决的问题之一是如何sleep实现这些目标。最终,它们最终会出现在某个地方的调度程序中,并且操作复杂性将取决于所使用的调度算法。例如,如果将sleeps作为事件放入优先级队列中,则最终可能会得到与堆排序等效的东西,复杂度为O(n log n)。天真的调度算法可能会导致O(n ^ 2)


19

我认为paxdiablo最接近,但不是出于正确的原因。时间复杂度忽略了实际硬件上的问题,例如缓存大小,内存限制,在这种情况下,进程数和调度程序的操作受到限制。

基于Wikipedia页面的时间复杂度,我会说答案是您无法确定运行时复杂度,因为如果将其定义为:

通常通过对算法执行的基本运算的数量进行计数来估算时间复杂度,其中基本运算需要固定的时间来执行。因此,算法花费的时间量和执行的基本运算的数量最多相差一个常数。

那么我们就不能谈论该算法的运行时间复杂性,因为基本操作所花费的时间差异很大,以至于所花费的时间相差一个常数以上。


“时间复杂度通常由...估算”,但不必通过计算基本操作来定义。谈论在特定时间段内睡眠的算法的时间复杂性是很有可能的。您可以计算他们的睡眠时间,然后对其进行渐进分析。
kaya3

13

该算法的时间复杂度和过程复杂度均为O(braindead)

  • 在数据集中具有足够大的值的情况下,您将等待答案直到太阳爆炸(2 64秒仅是半个万亿年之久)。
  • 如果数据集大小足够大您将(a)达到过程限制;和(b)发现,早睡觉将完成后面的一些开始之前,这意味着该组(2,9,9,9,9,9,...,9,9,1)不会排序12正确。

在这种情况下,时间复杂度无关紧要。没有比“错误”更好的优化了。可以使用复杂度分析在数据集大小变化时比较算法,但是当算法一开始就很荒唐时就不可以:-)


2
为了使它继续工作,您需要增加睡眠时间,以使连续编号之间​​的最小时间差大于排队所有睡眠的时间。这可能是O(n log n)假设内核中有一个有效的唤醒队列算法。我认为这仍然归结为O(n log n)CPU时间,可能还有非常差的挂钟时间。
彼得·科德斯

3

我和Jordan在一起,除了我认为挂钟时间复杂度最好用O(2 ^ m)表示,其中m是每个项目的大小,而不是O(max(input))。

如果每个项目的大小为m,则最大项目的整数值为2 ^ m(减1,但没有人关心)。通过构造,该算法要求建立时间小于1(恒定)。

因此,挂钟时间复杂度O(2 ^ m),操作计数复杂度O(n)。

考虑到建立时间的改进算法可能具有挂钟时间复杂度O(2 ^ m + n)。例如,它可以在开始时记下当前时间,进行计算base_time = start_time + k*len(list)(对于某个适当的常数k),然后让线程休眠直到time base_time+i。那么k*len(list)显然是O(n)并且i像以前一样是O(2 ^ m),总共是O(2 ^ m + n)。


2

如果您阅读了该主题,将会看到您的问题已得到回答。时间复杂度为O(max(input)),操作复杂度(操作数)为O(n)


2
线程肯定有一个答案,但我不知道它是否正确
justinhj 2011年

2

虽然看起来像线性,但我认为复杂度仍然是O(log(n)* max(input))。

当我们讨论渐近时间复杂度时,它意味着n无限大时要花费多少时间。

基于比较的排序算法不能快于O(n * log(n)),并且Sleep-Sort实际上是基于比较的:

进程休眠n秒然后唤醒。操作系统需要从所有睡眠过程中找到最少的剩余睡眠时间,如果需要的话,将其唤醒。

这将需要一个优先级队列,该队列需要O(logN)的时间来插入元素,并且O(1)会找到最小的元素,而O(logN)会删除最小的元素。

当n变得非常大时,将花费超过1秒的时间来唤醒进程,这使其大于O(n)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.