java - 这种类型存在吗?

标签 java algorithm sorting

我一直在浏览我的一些关于算法的旧书,并学习不同种类的排序。看起来所有最快的排序算法都在大约 O(nLogn) 时间内运行,这让我开始思考为什么这是我们能做的最好的事情?我写了另一种算法,它似乎在某些情况下运行得更好(除非我错过了什么),但在其他情况下却非常糟糕。这是否已经是一种正在使用的算法,而我只是在这里重新发明轮子?

public class Main {

public static void main(String[] args) {
    // array sort looks like it performs best in this example.
    // this is because N is pretty close in value to (max - min) in the array
    int[] arr = { 5, 26, 3, 32, 27, 9, 24, 29, 6, 37, 16, 10, 12, 28, 31, 22, 8, 20, 18, 2, 35, 14, 36, 7, 4, 15, 21};
    arraySort(arr);
    for (int i = 0; i < arr.length; i++) {
        System.out.print(arr[i] + " ");
    }

    // array sort does very poorly here.
    // this is because N is 4 which is very far from the value (max - min = 999) in the array
    int[] arr2 = {1, 1000, 100, 10};
    arraySort(arr2);
    for (int i = 0; i < arr2.length; i++) {
        System.out.print(arr2[i] + " ");
    }

    // I think an algorithm could first check if N and maxDifference are close, then it could
    // make sure that maxDifference is not so big that we start to care about size constraints.
    // If it meets those criteria, we can use arraySort, and if not we can use quicksort.
}

/**
 * Sorts in O(N) + O(maxDifference), where maxDifference is the difference between
 * the maximum and minimum values in the array.  Spatial complexity is an array of
 * size maxDifference.
 */
private static void arraySort(int[] arr) {
    if (arr==null || arr.length ==1){//no need to sort
        return;
    }
    int loopCount = 0;  // used for computing the algorithm's complexity
    int min = arr[0];
    int max = arr[0];
    // get the max and min values
    for (int i = 0; i < arr.length; i++) {
        loopCount++;
        int element = arr[i];
        if (element < min) {
            min = element;
        } else if (element > max) {
            max = element;
        }
    }
    int maxDifference = max - min;
    // create a boolean array of size maxDifference.
    // spatial complexity can get pretty bad when 
    // there is a huge maxDifference
    boolean[] positions = new boolean[maxDifference + 1];
    for (int i = 0; i < arr.length; i++) {
        loopCount++;
        int element = arr[i];
        // flag this position as true for later traversal
        positions[element - min] = true;
    }

    int count = 0;
    // traverse the array
    for (int i = 0; i < positions.length; i++) {
        loopCount++;
        boolean element = positions[i];
        if (element) {
            // insert the number into the sorted array
            arr[count++] = i + min;
        }
    }
    int qsortComplexity = (int) (arr.length * Math.log(arr.length)/Math.log(2));
    double isortComplexity = Math.pow(arr.length, 2);
    System.out.println("N = " + arr.length);
    System.out.println("spatial complexity = " + maxDifference);
    System.out.println("complexity = " + loopCount);
    System.out.println("qsortComplexity~= " + qsortComplexity + " isortComplexity~= " + isortComplexity);
}

编辑 如果有人感兴趣,我会继续修改它以接受重复项,这样它更像是计数排序。

public class Main {

public static void main(String[] args) {
    // array sort looks like it performs best in this example.
    // this is because N is pretty close in value to (max - min) in the array
    int[] arr = { 5, 26, 3, 32, 27, 9, 24, 29, 6, 37, 16, 10, 12, 28, 31, 22, 8, 20, 18, 2, 35, 14, 36, 7, 4, 15, 21};
    countingSort(arr);
    for (int i = 0; i < arr.length; i++) {
        System.out.print(arr[i] + " ");
    }

    // array sort does very poorly here.
    // this is because N is 4 which is very far from the value (max - min = 999) in the array
    int[] arr2 = {1, 1000, 100, 10};
    countingSort(arr2);
    for (int i = 0; i < arr2.length; i++) {
        System.out.print(arr2[i] + " ");
    }

    // testing duplicates
    int[] arr3 = {10, 10, 9, 5, 6, 6, 4, 3, 7, 4, 10, 5, 3, 8, 2, 9};
    countingSort(arr3);
    for (int i = 0; i < arr3.length; i++) {
        System.out.print(arr3[i] + " ");
    }

}

/**
 * Sorts in O(N) + O(maxDifference), where maxDifference is the difference between
 * the maximum and minimum values in the array.  Spatial complexity is an array of
 * size maxDifference.
 */
private static void countingSort(int[] arr) {
    if (arr==null || arr.length ==1){//no need to sort
        return;
    }
    int loopCount = 0;  // used for computing the algorithm's complexity
    int min = arr[0];
    int max = arr[0];
    // get the max and min values
    for (int i = 0; i < arr.length; i++) {
        loopCount++;
        int element = arr[i];
        if (element < min) {
            min = element;
        } else if (element > max) {
            max = element;
        }
    }
    int maxDifference = max - min;
    int[] positionCounts = new int[maxDifference + 1];
    for (int i = 0; i < arr.length; i++) {
        loopCount++;
        int element = arr[i];
        // add to the count at that position
        positionCounts[element - min] +=1;
    }

    int count = 0;
    // traverse the array
    for (int i = 0; i < positionCounts.length; i++) {
        int element = positionCounts[i];
        if (element == 0){
            loopCount++;
        }
        for (int j=0; j<element; j++){
            // insert the number into the sorted array
            arr[count++] = i + min;
            loopCount++;
        }

    }
    int qsortComplexity = (int) (arr.length * Math.log(arr.length)/Math.log(2));
    double isortComplexity = Math.pow(arr.length, 2);
    System.out.println("N = " + arr.length);
    System.out.println("spatial complexity = " + maxDifference);
    System.out.println("complexity = " + loopCount);
    System.out.println("qsortComplexity~= " + qsortComplexity + " isortComplexity~= " + isortComplexity);
}

最佳答案

您重新发明了 counting sort 的变体 [*] .

这不是 comparison sorting算法,因此 Ω(n log n) 最坏情况比较次数的下限不适用:该算法确实可以在更少的操作中运行,前提是满足某些条件:

  • 主要条件是值的范围是有限的(范围是算法时间复杂度中的一项)。
  • 对于您的算法,另一个条件是元素是唯一的。

计数排序和其他相关算法——例如bucket sort , radix sort等等 - 是您工具箱中的有用工具。它们不像快速排序那样普遍适用,但在合适的情况下可以成为合适的工具。参见维基百科 comparison of bucket sort with other algorithms .

[*] 顾名思义,经典计数排序计算值而不是使用 boolean 标志,因此更通用。您的算法无法正确处理重复元素:它会丢失除其中一个以外的所有元素。

关于java - 这种类型存在吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27691892/

相关文章:

java - 使用 Spring 框架的 WebSocketClient 时如何修复 NoClassDefFoundError

algorithm - 图吞吐量算法

c++如何按每行列中的值对二维 vector 的行进行排序

python - 如果值相同,如何对字典中的键进行排序?

java - 为拍卖创建构造函数,该构造函数生成一个包含先前未售出商品的 ArrayList 的对象

java - 为什么我在使用 RemoteFileTemplate 时会在日志中收到意外的 RuntimeException 警告?

java - 给定表达式树时创建字符串表达式

c# - 回溯搜索算法

algorithm - 在偏序集中查找大于给定的元素

java - 输入已排序的文件,对其进行取消排序,然后输出未排序的文件(Java)