簡體   English   中英

競速java.util.Collections.sort

[英]Racing java.util.Collections.sort

我發現了一種效率更高的排序算法,該算法具有O(N)的平均性能和最佳性能,而O(N Log(N))的性能最差。 關於均勻分布的數據

我需要您的幫助來告訴我測試是否正確,我最大的問題是:如何在真實數據上進行測試?

這個問題將包括五個部分:

  • 關於java.util.Collections.sort的簡短摘要
  • 關於我的算法的說明
  • 測試輸出
  • 我算法的源代碼
  • 我的測試程序的源代碼

關於java.util.Collections.sort的簡短摘要

Java在Collections.sort實現中使用模式化的合並排序算法。 從jdk 7開始,它已 timsort 取代 在測試中,我一直在研究jdk6。與Android相同。

關於我的算法的說明

我找到了一種有趣的排序方法。 我使用統計排序。 或更確切地說是線性統計排序。 我假設所有變量都具有“良好”的線性回歸 因此,我正在基於變量的值計算其近似索引。 如果多個變量具有相同的索引,則將其放在緩沖區數組中。 比我使用Collections.sort()對緩沖區排序。 想法是緩沖區將非常小,因此排序將為〜O(1)。 這是O(N)和O(N Log(N))的性能之間的差異,在最壞的情況下,它的大小為N。此后,我在近似排序的數組和緩沖區之間合並。 結果是排序數組。

測試輸出

  • 我的時間/系統時間= 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.7152777777777778

我算法的源代碼

    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);
}

將您的排序與Collections.sort的算法進行比較存在一個主要問題:

Collections.sort必然是一個純粹的比較排序 ,它所具有的一種方法是辨別2個對象中的哪個較小,在最壞的情況下,所有比較排序都可證明是下界O(n log n)

您的排序不適用於任意對象,因為您需要一個O(1)估計量,該值將在最終數組中的位置

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM