1

Код:

public static void raschestkaSort(int[] a){
    for(int d = a.length - 2; d >= 0; d--){
        for(int i = 0; i <= (a.length - 2) - d; i++){
            if(a[i] > a[i + d + 1]){
                swap(a, i, i + d + 1);
            }
        }
    }
}
private static void swap(int[] a, int from, int to) {
    int temp = a[from];
    a[from] = a[to];
    a[to] = temp;
}

В наихудшем случае сложность алгоритма должна быть равна O(1 + 2 + 3 + ... + (n - 1)). В вики же - O(n^2). Может, я неправильно считаю сложность?

P.S.: И действительно, если запустить сортировку с таким кодом:

public static void raschestkaSort(int[] a){
    int countOfComparing = 0;
    for(int d = a.length - 2; d >= 0; d--){
        for(int i = 0; i <= (a.length - 2) - d; i++){
            countOfComparing++;
            if(a[i] > a[i + d + 1]){
                swap(a, i, i + d + 1);
            }
        }
    }
    System.out.println(countOfComparing);
}

То для 14 элементов сравнений будет 91. А это близко не O(n^2)

insolor
  • 49,104
Miron
  • 3,027
  • 1+2+3+...+(n-1) = (n-1)*n/2 Вопросы есть? – Harry Feb 12 '20 at 15:36
  • @Harry Так, это будет (1 + (n - 1)) * n/2, я ошибаюсь? – Miron Feb 12 '20 at 15:38
  • то есть n^2 / 2, но это же все равно меньше, чем в вики. В целых 2 раза – Miron Feb 12 '20 at 15:39
  • @Miron, там не просто так считается, как обычное уравнение. Там берется самый большой степень, т.е. 1/2 мы упускаем. – entithat Feb 12 '20 at 15:42

2 Answers2

2

Во-первых,

введите сюда описание изображения

Т.е. чистое O(n^2)

Далее, O(n^2) не означает, что надо возвести n в квадрат, и это и будет число сравнений. Попробуйте несколько раз увеличить n раз в 5 и посмотрите на результаты...

Почитайте, что означает запись O(f(n)).

И 1000000000n^2+100n, и n^2/100000000+100n - это все O(n^2).

P.S. И вообще, давно и строго доказано, что алгоритм сортировки, основанный на сравнениях, не может быть лучше O(N * log N)...

Harry
  • 221,325
  • Почитал. "с увеличением параметра n, характеризующего количество входной информации алгоритма, время работы алгоритма будет возрастать не быстрее, чем некоторая константа, умноженная на f(n);" - все четко. наша константа указывает на скорость, с которой возрастает сложность. Неужели в нашем случае это не так - есть что-то еще кроме операций сравнения, на что нужно обращать внимание при оценке сложности?(неужели это КОЛИЧЕСТВО СВАПОВ? Тогда все сходится!(или нет?)). – Miron Feb 12 '20 at 15:51
  • Понимаете, ну нет тут конкретной константы. Как вот, например, вы не задумывались, почему в O(nlog n) не указывается*, какой именно логарифм? Потому что это неважно - любые два логарифма с разными основаниями отличаются на константный множитель. Ну неважно это - n^2/2 или 10000n^2. Главное - вид зависимости... – Harry Feb 12 '20 at 15:54
  • Имеете ввиду производную? – Miron Feb 12 '20 at 15:55
  • Вы имеете ввиду, что n^2 / (n-1)^2 просто должна быть константой? – Miron Feb 12 '20 at 15:57
  • Да при чем тут производная... Разве что в правиле Лопиталя :) Почитайте первую главу этой книги: https://e-maxx.ru/bookz/files/cormen.pdf – Harry Feb 12 '20 at 15:57
  • Прочитал полностью. Формула сложности(в их понимании) - это просто количество строк, пройденное программой. Мы же считаем количество сравнений, ибо изменяются только они(за исключением кол-ва вызовов swap). Почему я сделал предположение о производной ? Потому, что производная - это скорость возрастания ф-ции. И это вполне вяжется с нашей концепцией сложности - например, для O(n^2) производная будет равна n, а для O(n * (n-1) / 2) - (n - 1)/2. Могу ошибаться, с производной знаком только поверхностно. – Miron Feb 12 '20 at 16:09
  • Ничего вы так и не поняли... Посмотрите себе тут книгу попроще, и все же постарайтесь врубиться в то, что такое сложность алгоритма... – Harry Feb 12 '20 at 17:47
  • https://www.youtube.com/watch?v=M3ghq2E9tPw - посмотрел, и, вроде, понятно. n - это что-то входящее, например, размерность массива(увеличивающая на k при своем увеличении на единицу). O(kn) - это относительное время выполнения. Например, один и тот же алгоритм будет выполняться на машине в 100 раз мощней в 100 раз быстрей. k - это то, на сколько в этих относительных единицах будет увеличиваться время выполнения при увеличении n на 1. Вот и все. – Miron Feb 12 '20 at 18:15
  • В нашем же случае при увеличении n на 1 скорость выполнения увеличивается на (n-1)/2, то есть k = (n-1)/2. То есть это O(((n-1) / 2) * n) сложность.Разве не так? – Miron Feb 12 '20 at 18:17
  • Вы не хотите врубиться в главное - в то, что никто никакие действия, вообще говоря, не считает. И не бывает O(3n^2+n-15), например. Это просто O(n^2). Учительствовать я не могу, а потому простите, но больше участвовать в этой сказке про белого бычка не буду. – Harry Feb 12 '20 at 18:25
  • А, не до конца досмотрел. Константы можно откинуть. А вот то, что НЕЛИНЕЙНО зависит от n, нужно оставить. – Miron Feb 12 '20 at 18:26
1

В асимптотической сложности константы нужно отбрасывать. Асимптотическая сложность - это относительная величина. Она определяет кол-во единиц времени. которое понадобится для выполнения алгоритма.
Думаю, это нужно проиллюстрировать - например, у нас есть ф-ция f(n), принимающая количество раз, которое нужно вывести строку "Hello world". Кол-во единиц времени, которое займет выполнение зависит только от числа n. И зависит напрямую - значит сложность будет напрямую зависеть от числа n, и, соответственно, будет равна O(n).
Зависит же кол-во единиц времени в случае с сортировкой массива алгоритмом raschestkaSort(a) ТОЛЬКО от размерности a. Возьмем размерность за число n. Кол-во единиц времени, которое займет выполнение зависит только от числа n. И зависит оно в следующем отношении - (1 + (n - 1)) * n/2 = n * n / 2 - это и есть O. То есть O(n * n / 2). Вспомним, в асимптотической сложности константы нужно отбрасывать. Тогда O(n * n). То есть та же сложность. что и в вики.

Miron
  • 3,027
  • Кроме первой фразы, остальное - набор слов. Что за то есть k=n?? – MBo Feb 13 '20 at 06:19
  • @MBo почти полностью поменял текст. – Miron Feb 13 '20 at 10:27
  • n в f(n) в примере со строкой - это число букв в строке. Вывод целиком зависит линейно от количество символов, т.е. O(n). – Suvitruf - Andrei Apanasik Feb 13 '20 at 10:38
  • @SuvitrufsaysReinstateMonica n - это "количество раз, которое нужно вывести строку "Hello world"". – Miron Feb 13 '20 at 10:43