Racing java.util.Collections.sort
我发现了一种更有效的排序算法,其平均和最佳性能为O(N),而最差性能为O(N Log(N))。在均匀分布数据上 我需要你的帮助来告诉我我的测试是否正确,我最大的问题是:如何在真实世界的数据上测试它 这个问题将分为五个部分:Racing java.util.Collections.sort,java,mergesort,timsort,Java,Mergesort,Timsort,我发现了一种更有效的排序算法,其平均和最佳性能为O(N),而最差性能为O(N Log(N))。在均匀分布数据上 我需要你的帮助来告诉我我的测试是否正确,我最大的问题是:如何在真实世界的数据上测试它 这个问题将分为五个部分: 关于java.util.Collections.sort的简短介绍 关于我的算法的解释 测试输出 我的算法的源代码 我的测试程序的源代码 关于java.util.Collections.sort的简短介绍 Java在实现中使用了模块化的算法。从jdk7开始,它一直在使用。
- 关于java.util.Collections.sort的简短介绍
- 关于我的算法的解释
- 测试输出
- 我的算法的源代码
- 我的测试程序的源代码
- 我的时间/系统时间=511/859=0.5948777648428405
- 我的时间/系统时间=417/467=0.892933618843683
- 我的时间/系统时间=309/403=0.7667493796526055
- 我的时间/系统时间=308/344=0.8953488372093024
- 我的时间/系统时间=204/483=0.422360248447205
- 我的时间/系统时间=204/368=0.5543478260869565
- 我的时间/系统时间=279/291=0.9587628865979382
- 我的时间/系统时间=206/288=0.71527778
将排序与
集合进行比较时存在一个主要问题。排序的算法:
Collections.sort
是一种纯粹必要的方法,它所能做的只是判断两个对象中哪一个更小,在最坏的情况下,所有比较排序都是可证明的下限O(n logn)
您的排序不能用于任意对象,因为您需要对值在最终数组中的位置进行O(1)估计请参见:您的问题不清楚。你想要有人检查你的代码吗?你可能应该把这个带到医院。简单地看一下,您可能没有考虑到ArrayList的增长扩展(每次将一个项插入到ArrayList或向量中,但无法放入数组,所有项都会复制到两倍大小的新数组中)。对于大型阵列,这是相当低效的。请务必设置初始容量。@kdgregory基数有其自身的缺点。我的算法没有任何限制。我的观点是,基本上实现了基数排序。当我看到相关的排序时,我看到了Flashsort,这正是您要实现的。@Ilya_Gazman Vector不是固定大小的。它像ArrayList一样增长,事实上,这里没有必要使用Vector。最主要的区别是向量运算总是同步的。我认为这并不能说明全部情况,因为快速排序也是基于比较的,它是Java中所有原始数字的首选算法。我很确信,像OP的想法这样的东西不被使用的原因是在最坏的情况下。@MarkoTopolnik这种算法还需要在值和它们在结果中的位置之间建立一个良好的线性关系,这并不总是常见的,你无论如何都要通过对整个事情进行快速排序来为此付出代价。这是真的,我无法与sort的所有功能竞争,因为我的算法仅限于数字。所以在我的限制范围内,我相信这是一个合法的种族。有时,您使用的是整数列表,这就是您想要排序的内容。
public class StatisticSort {
private static long minemum;
private static long sum;
public static void sort(List<Integer> source) {
findMinMaxAndSum(source);
int size = source.size();
ArrayList<Integer> buffer = new ArrayList<Integer>();
Vector<Integer> sourceVector = new Vector<Integer>(size);
sourceVector.setSize(size);
for (int i = 0; i < size; i++) {
Integer ai = source.get(i);
int index = calculateIndex(ai, source);
if (index != i && sourceVector.get(index) == null) {
sourceVector.set(index, ai);
}
else {
buffer.add(ai); // value
}
}
Collections.sort(buffer);
int bufferSize = buffer.size();
for (int i = 0, j = 0, counter = 0; i < size || j < bufferSize;) {
if (i < size && j < bufferSize) {
Integer ai = sourceVector.get(i);
while (ai == null && i < size) {
i++;
if (i < size) {
ai = sourceVector.get(i);
}
}
if (i == size) {
continue;
}
Integer aj = buffer.get(j);
if (aj < ai) {
source.set(counter, aj);
j++;
}
else {
source.set(counter, ai);
i++;
}
counter++;
}
else {
if (i < size) {
Integer ai = sourceVector.get(i);
if (ai != null) {
source.set(counter, ai);
counter++;
}
i++;
}
else if (j < bufferSize) {
Integer aj = buffer.get(j);
source.set(counter, aj);
j++;
counter++;
}
}
}
}
private static int calculateIndex(Integer ai, List<Integer> source) {
int size = source.size();
return Math.min(size - 1, (int) (((ai - minemum) * size * (size - 1)) / (2 * (sum - size * minemum))));
}
private static void findMinMaxAndSum(List<Integer> source) {
long minemum = Long.MAX_VALUE;
long maximum = -Long.MAX_VALUE;
long sum = 0;
for (int value : source) {
sum += value;
if (value < minemum) {
minemum = value;
}
if (value > maximum) {
maximum = value;
}
}
StatisticSort.minemum = minemum;
StatisticSort.sum = sum;
}
}
public abstract class Test {
protected ArrayList<ArrayList<Integer>> buffer;
private final Random random = new Random();
public int numberOfTests = 100;
public int maxValue = 1000;
public int numberOfItems = 100;
protected void createBuffer() {
buffer = new ArrayList<ArrayList<Integer>>();
for (int i = 0; i < numberOfTests; i++) {
ArrayList<Integer> list = new ArrayList<Integer>();
addRandomNumbers(list);
buffer.add(list);
}
}
protected void createBuffer(int...parametes) {
buffer = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> list = new ArrayList<Integer>();
for(int i = 0; i < parametes.length; i++){
list.add(parametes[i]);
}
buffer.add(list);
}
protected void addRandomNumbers(ArrayList<Integer> list) {
for (int i = 0; i < numberOfItems; i++) {
int value = random.nextInt(maxValue);
list.add(value);
}
}
protected ArrayList<ArrayList<Integer>> cloneBuffer() {
ArrayList<ArrayList<Integer>> clonedBuffer = new ArrayList<ArrayList<Integer>>();
for(int i = 0; i < buffer.size(); i++){
ArrayList<Integer> clonedList = new ArrayList<Integer>();
ArrayList<Integer> list = buffer.get(i);
for(int element : list){
clonedList.add(element);
}
clonedBuffer.add(clonedList);
}
return clonedBuffer;
}
public abstract void test();
}
public class TestPerformance extends Test{
private final Timer timer = new Timer();
public void test() {
createBuffer();
timer.reset();
testSystem();
timeResoult("System");
timer.reset();
testMy();
timeResoult("My List");
}
public void test(int numberOfTests) {
long myTotalTime = 0;
long systemTotalTime = 0;
for(int i = 0; i < numberOfTests; i++){
createBuffer();
timer.reset();
testSystem();
long systemTime = timeResoult();
systemTotalTime += systemTime;
timer.reset();
testMy();
long myTime = timeResoult();
myTotalTime += myTime;
System.out.println("My Time / System Time = " + myTime + " / " + systemTime + " = \t" + ((double) myTime / systemTime));
}
System.out.println("My Time / System Time = " + ((double) myTotalTime / systemTotalTime));
}
private long timeResoult() {
return timeResoult(null);
}
private long timeResoult(String source) {
long time = timer.check();
if (source != null) {
System.out.println(source + ">\tTime: " + time);
}
return time;
}
private void testMy() {
ArrayList<ArrayList<Integer>> buffer = cloneBuffer();
for (int i = 0; i < numberOfTests; i++) {
ArrayList<Integer> list = buffer.get(i);
StatisticSort.sort(list);
}
}
private void testSystem() {
ArrayList<ArrayList<Integer>> buffer = cloneBuffer();
for (int i = 0; i < numberOfTests; i++) {
ArrayList<Integer> list = buffer.get(i);
Collections.sort(list);
}
}
}
public static void main(String[] args) {
TestPerformance testBasics = new TestPerformance();
testBasics.numberOfTests = 1000;
testBasics.numberOfItems = 1000;
testBasics.maxValue = 1000000;
testBasics.test(1000);
}