注意:以下排序不要用于生产环境
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. 总结
这两个排序算法可以说是排序算法界的卧龙凤雏,建议大家还是不要在生产环境使用。