排序算法 Sleep Sort

排序算法 Sleep Sort

排序算法好像是程序员学习编程最多的算法,也可能是算法研究者们最喜欢研究的算法了。排序有很多很多的算法,比如,冒泡,插入,选择,堆,快速,归并等等(你可以看看本站以前的那些文章:可视化的排序排序算法比较显示排序过程的python)这里向大家介绍一个“巨NB”的排序算法——Sleep Sort。

闲言少说,请看下面的代码(用Shell脚本写的)

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

用法如下:

./sleepsort.bash 5 3 6 3 6 3 1 4 7

相信你可以会去试一下这个脚本,也相你你试完后你一定会说——“我擦,真TMD排序了!”,我还是不要解释这段代码了,过多的解释会不如代码那么直接,而且解释会影响你对这个排序算法的NB性。只想说——这是正二八经的多线程、多进程排序啊。我们的Bogo排序也黯然失色啊。

下面我们需要对这个算法做一些分析——

1)让我们来分析一个这这个程序的算法复杂度,太简单了,不就是O(最大数的秒数),呵呵。所以,如果出现这样的数列将是恶梦的——2 1 4 3 2 1 99999999

2)这个排序好是好,但对于负数或浮点数就有bug了。负数的解决方案是,我们可以这样来:x/2+MaxInt/2(时间可能相当长,不过依然工作)。对于浮点数,看看下面的代码.

#!/bin/bash
function f() {
  sleep $(echo "($2 - 1) + $1 / 10 ^ $2" | bc -l)
  echo "$1"
}
while [ -n "$1" ]
do
  f "$1" $(echo -n "$1" | wc -c) &
  shift
done
wait

3)我们来看看各种语言版本的实现吧。
Java

public class SleepSort {
    public static void main(String[] args) {
        int[] ints = {1,4,7,3,8,9,2,6,5};
        SortThread[] sortThreads = new SortThread[ints.length];
        for (int i = 0; i < sortThreads.length; i++) {
            sortThreads[i] = new SortThread(ints[i]);
        }
        for (int i = 0; i < sortThreads.length; i++) {
            sortThreads[i].start();
        }
    }
}
class SortThread extends Thread{
    int ms = 0;
    public SortThread(int ms){
        this.ms = ms;
    }
    public void run(){
        try {
            sleep(ms*10+10);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println(ms);
    }
}

Javascript

[javascript]function sleepsort() {
for (var i = 0, il = arguments.length; i < il; i++) {
(function(args, index) {
setTimeout(function() {
document.body.innerHTML += args[index] + ‘, ‘;
}, args[index]);
}(arguments, i));
}
};
[/javascript]

Brainfuck (关于这门语言,请参看这篇文章)

,>,>++++++++[<------<------>>-]
<<[>[>+>+<<-]>>[<<+,>,>++++++++[<------<------>>-]
<<[ ----------[++++++++++>----------]++++++++++
>[>+>+<<-]>>[<<+>>-]<<<-] >>>++++++[<++++++++>-]<.>.>>-]<<<-]
,----------[----------------------.,----------]
,---<<<+>>>-------[----------------------.,----------]
>> ----------[++++++++++>----------]++++++++++
>++++++[<++++++++>-]< ----------[++++++++++>----------]++++++++++
.>. ----------[++++++++++>----------]++++++++++
>++>+<<-]>>[<<+>>-]<<<-] >>[>[>+>+<<-]>>[<<----------[++++++++++>----------]++++++++++
>++,>,>++++++++[<------<------>>-]
<<

(全文完)

(转载本站文章请注明作者和出处 酷 壳 – CoolShell ,请勿用于任何商业用途)

好烂啊有点差凑合看看还不错很精彩 (23 人打了分,平均分: 4.00 )
Loading...

排序算法 Sleep Sort》的相关评论

  1. 外一数组中有一个数是“Integer.MAX_VALUE”,看看这算法要多久才能排完。哈哈。

  2. 来一个python的版本:

    import threading
    def sleepsort(num):
    print num,” “;
    if __name__ == ‘__main__’:
    for num in input(” input a python list of int:”):
    (threading.Timer(num,sleepsort,(num,),{})).start();

  3. 个人觉得真的很”NB”
    如果数组里有一堆的相等的数值呢? 输出还可以, 但对结果数组操作的时候, 会…..?
    在java下测试, 经常会出现这种情况:整体基本增序, 但是偶有, 几个跳梁的小丑让你乱一下. 先声明, 已经上锁, 如果不上锁的时候, 有可能出null, 甚至直接挂掉.

  4. 时间可以设短点, 可以把排序的数做log, 这样复杂度可以减少到logN. 还可以先hash一遍到一个固定的范围里面,这样可以做到O(1). (hash能否做到还需要看具体的分布..)

  5. 没有考虑代码执行的时间,要排序的数据达到一定的量后就会出错,特别是数据量大,又小数据在后面的情况!拓展拓展思路不错!

  6. Brainfuck的跑不动啊:
    Error: Unbalanced brackets.
    an error occured

    用的Ubuntu的bf包

  7. java代码靠线程的睡眠时间等于是依靠线程的调度的顺序,而且这个代码所有的线程不是一起开始的。
    算法应该不能保证绝对的正确性

  8. 33楼说得有理,在java下线程睡醒后能否马上运行要看调度者的意思啊。在数据大小比较相近的情况下会出现顺序错乱吧?!

  9. 哈哈,这个算法太有创意了,不过权当娱乐吧,真用起来恐怕有不少问题

    1.如果某个数非常大,直接导致时间复杂度的飙升

    2.如果要排序的数据量很多,因为一个数字对应一个线程,可能导致系统资源耗尽

  10. 你以為他為什麼會照順序出來, 其實是 scheduler 排的呀!
    所以這只是把排序 delegate 給 scheduler, 你們認為 scheduler 的時間空間複雜度是多少?

  11. 呵呵,这个在有很多数值一样,并且存在和这些一样的数相近的数时,排序的结果可能不准确吧

  12. /*****************C++0x version******************************/
    #include
    #include
    #include
    #include

    int main(int argc, char* argv[]) {

    std::list v ;
    for (int i(1) ; i void {
    std::this_thread::sleep_for( std::chrono::duration(num) ) ;
    std::cout << num << std::endl ;
    }) ;
    }

    for ( auto & t : v ) { t.join() ; }

    return 0;
    }

  13. linux新手,

    function f() {
    sleep “$1”
    echo “$1”
    }

    我这里这样写会报错,把 function 去掉成功:

    f() {
    sleep “$1”
    echo “$1”
    }

  14. 这个排序不稳定,如果 输出的时间相对sleep较大 有时候不是完全有序
    如果整数很多 不是要sleep很久??

  15. 这个时间复杂度的分析,我觉得有问题。“最大数的秒数”不是问题的规模。举例子说,O(n)中的n是问题的规模,而O(n)表示的是随着问题规模的变化,某算法对某计算资源,如时间,变化的趋势。这里,按我的理解分析一下。假设M为最大的整数。当只有一个元素被排序时,即n=1,平均所需时间为: sum(0:M)/M。当有两个元素排序时,每一种选择的排序时间为两者之间的大数。当一个数固定是,平均排序时间还是sum(0:M)/M。例如,(1,0),(1,1),…, (1,M)的排序时间分别为(0,1…,M)。这样的两个元素序列有M种,每种的平均排序时间都是sum(0:M)/M。那么,当n=2时,平均时间为sum(0:M)/M。依次类推,递归可得当n=M时,平均排序时间仍然是sum(0:M)/M。所以这个问题的O(n)应该是0,因为该算法的平均耗费时间是固定的,即sum(0:M)/M。另外,如果在单CPU上,M的值还要收进程数上限的制约。如果小数都在面可以多排些。大数在前面多的话,后面的可能就没有进程分了。当进程间切换时期超过一秒时,会不会出现问题呢?

    还要注意的时,该算法在多CPU时完全没有scalability。

    拙见,

    马。

  16. 。。干嘛去很细节的研究这个性能呢。。博主也只是想传达一个信息“哇,这都行。真新奇”。。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注