珠排序的原理如图:
定义和图片引用详见排序算法详解(Java实现 + 动画演示)_javagui排序算法动画-CSDN博客
代码实现如下:
package org.xxxxx.modules.util;
import lombok.Data;
import java.util.*;
public class PearlTest {
public static void main(String[] args) {
List<Integer> randomVauleList = RandomIntegerUtils.getRandomIntegers(0, 100, 10);
long st = System.currentTimeMillis();
PearlSort result = new PearlSort(randomVauleList);
System.out.println(result.rawList);
System.out.println(result.sortList);
System.out.println(System.currentTimeMillis() - st);
}
@Data
private static final class PearlSort {
/**
* 珠盘
*/
private final List<LinkedList<Integer>> abacus = new LinkedList<>();
/**
* 原数字顺序
*/
private final List<Integer> rawList;
/**
* 排序后的顺序
*/
private final List<Integer> sortList;
public PearlSort(List<Integer> rawList) {
this.rawList = rawList;
this.sortList = new ArrayList<>();
this.rawList.removeIf(Objects::isNull);
for (Integer value : this.rawList) {
//添加珠子到珠盘并坠落
addPearl(value);
}
//统计珠盘的珠子
pearlFall(sortList);
}
private void pearlFall(List<Integer> sortList) {
while (abacus.size() > 0){
int value = 0;
for (LinkedList<Integer> bunch : abacus) {
if (bunch.size() > 0){
bunch.removeFirst();
value++;
}
}
abacus.removeIf(AbstractCollection::isEmpty);
sortList.add(value);
}
}
private void addPearl(Integer value) {
autoSizeByValue(value);
for (int i = 0; i < value; i++) {
List<Integer> bunch = abacus.get(i);
bunch.add(0);
}
}
private void autoSizeByValue(Integer value) {
int increment = value - abacus.size();
if (increment > 0){
for (int i = 0; i < increment; i++) {
abacus.add(new LinkedList<>());
}
}
}
}
}
其中工具类RandomIntegerUtils实现详见猴子排序详解-CSDN博客
运行结果如下:
可以看出珠排序的算法时间复杂度和空间复杂度不仅和排序数字的个数n有关,还和排序数字的最大值vmax大小有关,有文章认为其时间复杂度是O(n), 实际运行却慢的多,这是因为没有考虑排序不仅要移动珠子,创建珠子将珠子放到珠盘也需要时间,所以时间复杂度必然和vmax有关。
分别添加2000,20000,200000,测试结果如下:
从结果中可以看出时间增长十分明显,但又不能用简单的vmax或者vmax的平方来描述它们的关系。总而言之这是一个仅在数字个数100以内,数字大小不超过10000时还可以一用的算法,不过如果你的电脑是某星文明的量子计算机,运算无限快,空间无限大,就算最大值是一个小目标应该也没有什么问题。