睡眠排序、面条排序、猴子排序...........................

内容整编自多个网友的文章,外加上自己的一些感想,链接太多就不一一列举了:)

1. 睡眠排序(Sleep Sort)

睡眠排序也称为硬件排序, 充分利用硬件计时器的资源实现拟态算法(逃

这个事件起源于一个屌丝发表了一个时间复杂度为O(n)的排序算法,睡眠排序的主要逻辑是构造n个线程,它们和这n个数一一对应。初始化后,线程们开始睡眠,等到对应的那么多个时间单位后各自醒来,然后输出对应的数。这样最小的数对应的线程最早醒来,这个数最早被输出。等所有线程都醒来,排序就结束了。能脑洞大开想出此算法的,绝壁天才啊。
于是我一本正经地试着实现一下这个Idea:

public class SleepSort {
    public static void main(String[] args){
        int[] nums={9,7,2,6,15,8,9,9,9,9,9};
        SleepSort.sort(nums);
        for(int n:nums)
            System.out.printf("%d   ",n);
    }
    public static void sort(int[] nums){
        Sleeper.idx=0;
        Sleeper.output=new int[nums.length];
        for(int i=0;i<nums.length;i++)        //[1]
            new Sleeper(nums[i]).start();
        
        for(int i=0;i<nums.length;i++)
            nums[i]=Sleeper.output[i];
    }
}
class Sleeper extends Thread{
    public static int[] output;
    public static int idx;
    private int sleep_time;
    public Sleeper(){
        this.sleep_time=0;
    }
    public Sleeper(int sleep_time){
        this.sleep_time=sleep_time;
    }
    @Override
    public void run(){
        try{
            Thread.sleep(this.sleep_time);
        }catch(InterruptedException e){
            e.printStackTrace();
        }
        output[idx++]=this.sleep_time;
    }
}

 

当然也可以用我大javascript setTimeout 实现:
 


let nums = [9,7,2,6,15,8,9,9,9,9,9]
, output = []

nums.forEach(function (num) {
setTimeout(function () {
output.push(num)
if (output.length == nums.length) {
console.log(output)
}
}, num)
})

算法其实真的很天才,让操作系统来处理排序的复杂度,而且很容易并行起来...不过最大的作用还开脑洞吧;

2. 面条排序(Spaghetti Sort, 意面排序)

首先去买一捆面,是意面挂面还是手擀面请按个人口味决定,最好是硬的。找到数组中最大和最小的两个数(O(n)),让最大的数对应一根很长的面条,最小的数对应一根很短的面条。重新遍历数组,每遇到一个数,就取一根面条,把它切成这个数对应的长度,可以得到n根面条。这里的数与面条长度的对应可以用一个严格递增的函数来映射。接下来,一手握住这n根面条,稍微用力,别握太紧,在平放的桌面上直立着放下,让所有的面条底端接触到桌面。另一只手平行于桌面,从面条上方缓慢往下移动,每当这只手碰到一根面条,移走它,并把对应的数输出到结果数组中,直到移走全部面条。
用完的面条还可以煮夜宵哦。
面条排序的思想基本上跟睡眠排序一样样的,公布程序

#include<iostream>
using namespace std;
int main()
{
int g;
cin>>g;
int a[g],count=0,i,ai;
for (i=0;i<g;i++)
cin>>a[i];
for (i=0;i<g;i++)
{
for (ai=0;i<g;i++)
{
a[ai]--;
if(a[ai]==0)
cout>>count+1;
}
count++;
}
return 0;
}

算法的意义在意,它是一个“算法”。要知道算法的概念远早于计算机,我们的代码都是对“算法”的模拟,也是对自然模拟,就好像数学物理学那样...跳出计算机思维之外,很多的问题都有很直观的解法,你可以认为是有趣的思维实验;

 

3. 猴子排序(Bogo Sort)

随机打乱数组,检查是否排好序,若是,则输出,否则再次打乱,再检查...最佳情况O(n),平均O(n*n!),最坏可执行直到世界的尽头。
算法代码主体部分基本上就是这样的:

while(! isOrdered(nums))
    shuffle(nums);

See also 无限猴子定理:一只猴子随机敲打打字机键盘,如果时间足够长,总是能打出特定的文本,比如莎士比亚全集。

注:

猴子那个一开始以为最好不应该是时间复杂度为1,因一次瞎排就得出结果. 但还得查看是否有序,这个过程耗的时,这是那个n

第三个算法,最大的意义也许在于观众看完之后的那句“卧槽这也行”、“这特么什么鬼”...-_-||

完整代码(c++):

#include <iostream>
using namespace std;
int source[10],flag[10],res[10];
int sort(){
    memset(flag,1,sizeof(flag));
    int num = 10,count=0;
    while(num){
        int t =rand()%10;   //生成0-9之间的数
        if(flag[t]){
            res[count++] = source[t];
            num--;
        }
    }
    for(int i=0;i<9;i++){
        if(res[i]>res[i+1]){      //只有是从小到大的排列才行
            return 0;
        } 
    }
    return 1;
}
int main(){
    int count = 0;
    for(int i=0;i<10;i++){
        cin>>source[i];
    }
    while(sort()!=1){
        count++;
    }
    cout<<"共运行了"<<count<<"次"<<endl;
    return 0;
}

 

posted @ 2018-11-23 16:42  xosg  阅读(1524)  评论(0编辑  收藏  举报