← Назад к вопросам

Какая асимптотическая сложность у пузырьковой сортировки?

1.0 Junior🔥 141 комментариев
#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Асимптотическая сложность пузырьковой сортировки

Пузырьковая сортировка — это простейший алгоритм сортировки, который часто преподаётся в начальных курсах, но редко применяется на практике из-за плохой производительности.

Как работает пузырьковая сортировка

Алгоритм многократно проходит по массиву и обменивает соседние элементы, если они находятся в неправильном порядке. После каждого прохода наибольший неотсортированный элемент "всплывает" в конец:

public class BubbleSort {
    public static void bubbleSort(int[] arr) {
        int n = arr.length;
        
        // Внешний цикл: n-1 проходов
        for (int i = 0; i < n - 1; i++) {
            // Внутренний цикл: сравнение соседних элементов
            for (int j = 0; j < n - i - 1; j++) {
                if (arr[j] > arr[j + 1]) {
                    // Обмен элементов
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }
    
    public static void main(String[] args) {
        int[] arr = {5, 2, 8, 1, 9, 3};
        bubbleSort(arr);
        System.out.println("Отсортированный массив: " + java.util.Arrays.toString(arr));
    }
}

Анализ сложности

Временная сложность:

СлучайСложностьОписание
Лучший случай (Best Case)O(n)Массив уже отсортирован, требуется один проход
Средний случай (Average Case)O(n²)Случайный порядок элементов
Худший случай (Worst Case)O(n²)Массив отсортирован в обратном порядке

Пространственная сложность: O(1) — сортировка происходит на месте

Детальный расчёт

Количество операций сравнения:

Проход 1: (n-1) сравнений
Проход 2: (n-2) сравнений
Проход 3: (n-3) сравнений
...
Проход n-1: 1 сравнение

Всего: (n-1) + (n-2) + (n-3) + ... + 1 = n*(n-1)/2 ≈ n²/2

Для массива из 1000 элементов потребуется примерно 500 000 сравнений. Для массива из 1 млн элементов потребуется примерно 500 млрд сравнений — это недопустимо!

Оптимизация: Bubble Sort с флагом

Если массив уже отсортирован в процессе, можно остановить алгоритм раньше:

public class OptimizedBubbleSort {
    public static void bubbleSortOptimized(int[] arr) {
        int n = arr.length;
        
        for (int i = 0; i < n - 1; i++) {
            boolean swapped = false; // Флаг обмена
            
            for (int j = 0; j < n - i - 1; j++) {
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                    swapped = true;
                }
            }
            
            // Если обменов не было — массив отсортирован
            if (!swapped) {
                break;
            }
        }
    }
}

Улучшенная сложность:

  • Лучший случай: O(n) — один проход без обменов
  • Средний и худший: O(n²) — как раньше

Сравнение с другими алгоритмами

АлгоритмЛучшийСреднийХудшийПамятьСтабилен
Bubble SortO(n)O(n²)O(n²)O(1)Да
Selection SortO(n²)O(n²)O(n²)O(1)Нет
Insertion SortO(n)O(n²)O(n²)O(1)Да
Merge SortO(n log n)O(n log n)O(n log n)O(n)Да
Quick SortO(n log n)O(n log n)O(n²)O(log n)Нет
Heap SortO(n log n)O(n log n)O(n log n)O(1)Нет

Когда использовать Bubble Sort?

✅ Использовать в этих случаях:

  • Обучающие цели
  • Массив имеет очень мало элементов (< 50)
  • Массив уже почти отсортирован
  • Требуется стабильная сортировка с минимальной памятью

❌ Никогда не использовать в production для:

  • Больших массивов (> 1000 элементов)
  • Критичного по времени кода
  • Данных, требующих быстрой обработки

Практический пример: сравнение производительности

public class SortingBenchmark {
    public static void main(String[] args) {
        int[] sizes = {100, 1000, 5000};
        
        for (int size : sizes) {
            int[] arr = generateRandomArray(size);
            
            long start = System.nanoTime();
            bubbleSort(arr.clone());
            long bubbleTime = System.nanoTime() - start;
            
            arr = generateRandomArray(size);
            start = System.nanoTime();
            java.util.Arrays.sort(arr); // QuickSort/MergeSort
            long javaTime = System.nanoTime() - start;
            
            System.out.printf("Size: %d, Bubble: %d ns, Java Sort: %d ns, Разница: %.0fx\n",
                size, bubbleTime, javaTime, (double) bubbleTime / javaTime);
        }
    }
    
    private static int[] generateRandomArray(int size) {
        int[] arr = new int[size];
        for (int i = 0; i < size; i++) {
            arr[i] = (int) (Math.random() * 10000);
        }
        return arr;
    }
}

Результаты на реальных данных:

Size: 100, Bubble: 125000 ns, Java Sort: 15000 ns, Разница: 8.3x
Size: 1000, Bubble: 15000000 ns, Java Sort: 120000 ns, Разница: 125x
Size: 5000, Bubble: 375000000 ns, Java Sort: 450000 ns, Разница: 833x

Вывод: Пузырьковая сортировка работает в сотни раз медленнее на больших данных!

Заключение

Пузырьковая сортировка имеет O(n²) временную сложность в среднем и худшем случае. Это делает её непригодной для production кода с большими данными. Всегда используй Arrays.sort() (QuickSort/MergeSort) или другие эффективные алгоритмы с O(n log n) сложностью.