Существует ли этот вид?

1

Я просматривал некоторые из моих старых книг по алгоритмам и узнал о разных видах. Похоже, что все быстрые алгоритмы сортировки работают примерно в 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 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 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);
}

}

  • 0
    JDK уже использует сортировку Merge, которая является O (nlogn), хорошо протестирована, так что вы просто заново изобретаете колесо.
  • 4
    Это действительно подсчет; O (n log n) - нижняя граница алгоритма сортировки сравнения , единственное предположение которого относительно элементов сравнимо.
Показать ещё 4 комментария
Теги:
algorithm
sorting

2 ответа

5
Лучший ответ

Вы заново изобрели вариант [*] сортировки.

Это не алгоритм сортировки сравнения, поэтому нижняя граница Ω(n log n) для наихудшего числа сравнений не применяется: этот алгоритм действительно может работать в меньшем количестве операций при условии выполнения определенных условий:

  • Основное условие заключается в том, что диапазон значений ограничен (и диапазон является одним из терминов в сложности времени алгоритма).
  • В случае вашего алгоритма другое условие состоит в том, что элементы уникальны.

Сортировка сортировки и другие связанные с ней алгоритмы, такие как сортировка ковша, сортировка по методу radix и т.д., Являются полезными инструментами для вашего инструментария. Они не так широко применимы, как подобные quicksort, но могут быть именно правильным инструментом в правильных обстоятельствах. См. Википедию для сравнения сортировки ковша с другими алгоритмами.

[*] Как видно из названия, классический подсчет сортирует значения вместо использования логических флагов, поэтому является более общим. Ваш алгоритм не может правильно обрабатывать повторяющиеся элементы: он потеряет все, кроме одного из них.

  • 0
    Круто, спасибо большое. В любом случае, это было забавное упражнение
  • 0
    @pickle_inspector: Абсолютно. Нет причин не играть с такими вещами - это отличный способ учиться!
0

Это похоже на сортировку, которая, как вы заметили, является хорошим решением для коллекций элементов с целыми ключами, чей спред не значительно больше числа элементов.

Сортировка счета - это вариант сортировки ведра с использованием ведра размера 1. Это увеличивает требования к памяти для сортировки, но снижает временную сложность.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню