内容整编自多个网友的文章,外加上自己的一些感想,链接太多就不一一列举了:)
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;
}