[卧龙凤雏]睡眠排序和随机排序
注意:以下排序不要用于生产环境
1. 睡眠排序
1.1 简介
睡眠排序(Sleep Sort)是一个非常有趣且奇特的排序算法,第一次看到就大吃一惊。睡眠排序并不是一个实际可用于大规模数据排序的算法,而更像是一种编程趣味或者计算机科学的玩笑。原理基于多线程和睡眠的概念,不是传统的比较排序算法。
睡眠排序的主要思想是将待排序的一组整数分配给多个线程,每个线程负责处理一个整数,它们根据整数的值来设置睡眠时间。整数越小,睡眠时间越短,整数越大,睡眠时间越长。当所有线程都完成睡眠后,它们按照睡眠时间的长短排列,从而实现排序。
主要思路:
- 创建一个数组,其中包含待排序的整数。
- 对于数组中的每个整数,创建一个线程来处理它。
- 每个线程计算自己要休眠的时间,通常是整数值乘以一个常数,以确保休眠时间的差异。
- 所有线程同时开始休眠。
- 当一个线程醒来后,它将自己的整数放入一个结果数组中。
- 重复步骤4和步骤5,直到所有线程都完成。
- 最后,结果数组中的整数按照休眠时间的升序排列,即得到排序后的结果。
限制:
- 不稳定性:由于线程的调度和休眠不稳定,这个算法不保证排序的稳定性。
- 效率问题:算法的效率极低,它的时间复杂度可以达到O(n^2)级别,这在实际应用中不可接受。
- 负整数问题:如果待排序数组包含负整数,那么这个算法会在负整数的线程上休眠很长时间,导致等待时间非常长。
1.2 代码实现
import java.util.Random;
import java.util.concurrent.CountDownLatch;
public class SleepSort {
public static void main(String[] args) throws InterruptedException {
int count = 100;
int[] nums = new int[count];
Random random = new Random();
// 限制程序不要过早中断
CountDownLatch countDownLatch = new CountDownLatch(count);
// 随机 100 个 1 - (10 * count) 的数
for (int i = 0; i < count; i++) {
nums[i] = random.nextInt(1, 10 * count);
}
// 开启虚拟线程,延迟一定时间后打印数字
for (int i = 0; i < count; i++) {
int num = nums[i];
Thread.startVirtualThread(() -> {
try {
Thread.sleep(10L * num);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(num);
countDownLatch.countDown();
});
}
countDownLatch.await();
}
}
2. 随机排序(猴子排序)
2.1 简介
随机排序,也称为乱序排序(Random Sort)、洗牌排序(Shuffle Sort)或猴子排序(Monkey Sort),特点是将待排序的元素随机排列。
主要思路:
- 输入待排序的元素组成的列表或数组。
- 对于列表中的每个元素,生成一个随机数或随机权重,并将元素与其对应的随机数关联。
- 根据随机数对元素进行排序。这通常可以使用标准的排序算法,如快速排序或归并排序,但比较的标准是元素的随机数而不是元素本身的值。
- 完成排序后,元素就会以随机的顺序排列。
限制:
- 随机性:由于随机数的引入,每次随机排序的结果都会不同,即使相同的输入数据也会产生不同的输出。
- 不稳定性:随机排序通常不保证排序的稳定性,因为它完全依赖于随机数。
- 低效性:随机排序的时间复杂度通常较高,取决于用于排序的具体算法。这远不如许多其他排序算法,因此不适合大规模数据集的排序任务。
2.2 代码实现
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
public class RandomSort {
public static void main(String[] args) throws InterruptedException {
// 这个数建议不要太大,不然要随机好久
int count = 5;
Random random = new Random();
// 限制主线程不要退出
CountDownLatch countDownLatch = new CountDownLatch(1);
int[] nums = new int[count];
for (int i = 0; i < count; i++) {
nums[i] = random.nextInt(10);
}
int[] sortedNums = Arrays.copyOf(nums, nums.length);
// 这里偷懒直接用sort方法,然后在下面直接判断
Arrays.sort(sortedNums);
long startTime = System.currentTimeMillis();
// 这里开一百万个虚拟线程随机
for (int i = 0; i < 1000000; i++) {
Thread.startVirtualThread(() -> {
while (countDownLatch.getCount() > 0){
int[] tmp = new int[count];
for (int j = 0; j < count; j++) {
tmp[j] = random.nextInt(10);
}
// 可以打印中间过程的输出
// System.out.println(Arrays.toString(tmp));
if (Arrays.equals(sortedNums, tmp)){
System.out.println("排序完毕:未排序数据" + Arrays.toString(nums));
System.out.println("排序完毕:已排序数据" + Arrays.toString(tmp));
countDownLatch.countDown();
break;
}
}
});
}
countDownLatch.await();
// 计算总时间
System.out.println(System.currentTimeMillis() - startTime);
}
}
3. 总结
这两个排序算法可以说是排序算法界的卧龙凤雏,建议大家还是不要在生产环境使用。