Рубрики
Без рубрики

Пузырись с пузырьками

Кажется, есть постоянная шутка: все, кажется, знают, что Bubble Sort – это плохая идея ™. Помечено алгоритмами, JavaScript, новичками, информатикой.

Там, кажется, постоянная шутка в сообществе программирования, которое выходит за пределы языка, библиотеки или рамки – все, кажется, знают, что Bubble Worth – это плохое представление «¢. Я помню, как слушал, что кто-то шутил об этом впервые лет назад; они были Rurking on Bubble Worth, смеясь на то, как это было худшая реализация алгоритма сортировки, и как они не могли понять, почему кто-то когда-либо использовал его.

Я слышал эту шутку снова и снова и снова в годы, и на некоторое время я только что принял его по значению лица. Иногда я даже смеялся вместе со всеми остальными, когда они делали шутку с пузырькой, не зная, почему люди думали, что это так ужасно. Обычно я думаю, что лучше принять свое мнение о чем -то, а не просто слушать чьи -то мнения об этом и принять их как Евангелие. Я сделал это долгое время с пузырем. Но на самом деле я не думаю, что это была хорошая практика.

Только когда я начал эту серию, что решил, что положил бы все это в сторону. Может быть, пузырьковая сортировка действительно ужасный алгоритм. Или, возможно, это просто неправильно понято или плохо используется. И, возможно, это даже может быть сделано лучше и оптимизировано. Как бы я когда -либо узнал об этих вещах, если я сам не узнал о них?

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

Базовые основы

Прежде чем мы действительно сможем сделать любые справедливые суждения на алгоритме сортировки пузыря, нам нужно понять, что именно это делает и как это работает. А Алгоритм сортировки пузыря С помощью списка или массива его дается, и сравнивает каждую пару соседних элементов в списке по размеру. Если они элементы находятся в неверном порядке, оно сводится к ним, а затем перемещается на следующую пару элементов.

Сортировка пузыря: определение

Определения – отличная отправная точка, но для меня вещи, действительно только цементируются, когда я вижу их на практике. Итак, давайте посмотрим на то, что это определение на самом деле означает с прагматичной точки зрения. В этом примере здесь у нас есть коллекция неупорядоченных чисел, которые необходимо отсортировать: 9, 7, 4, 1, 2. Как бы сортировать Bubble Sort?

Как Bubble Sort сравнивает два элемента

Ну, мы знаем, что пузырьковые сортировки будут сравнивать две пары за раз. Естественно, он начнется сравнивать первые два элемента в нашем списке – первая пара. Алгоритмы смотрит на первую пару (в этом случае 9 и 7) и определяют, находится ли первый элемент в правильном месте. Эффективно, он просто использует A> или <оператор для этого, в зависимости от того, как реализован вид.

С 9 превышает 7, алгоритм знает, что он должен прийти после 7. Поскольку эти два номера в неверном порядке относительно друг друга , он поменят их, что изменит порядок только те два элемента в списке. Имейте в виду, что он понятия не имеет, является ли 9 самым большим числом в списке – он знает только о двух числах в любом данном точке, поскольку алгоритм не может быстро сканировать список, как мы можем.

Хорошо, так вот как это функционирует алгоритм сортировки пузыря при сравнении двух элементов одновременно. Но как это на самом деле сортирует весь список? Давайте посмотрим на то, что будет делать алгоритм, используя то же самое набор номеров в нашем примере:

Один проход/итерация пузырьковой сортировки

Мы начинаем сравнивать первые два элемента – 9 и 7, и, поскольку они вышли из строя, мы поменяем их.

Далее мы сравниваем второй и третий элементы: 9 и 4. Номер 9 определенно больше 4, поэтому он должен прийти после. Это означает, что мы должны поменяться этим двум элементам.

Следующие два элемента 9 и 1. Опять же, 9 должны прийти после 1, а не раньше, что означает, что нам нужно поменять снова Отказ Наконец, мы на последних двух элементах в этой итерации: 9 и 2. Номер 2 обязательно должен прийти до 9, поэтому мы поменяем эти два элемента, чтобы они в правильном порядке.

Фу! Это была только одна итерация пузырькового сорта. И наш список еще даже не отсортирован . Нам нужно будет повторять этот набор действий снова и снова, пока вся коллекция элементов не была отсортирована. Если это было просто одинокий Итерация, есть один большой вопрос в моем уме сейчас: сколько раз мы должны были бы передать, чтобы разобраться всю коллекцию? Представьте, что если у нас был список из 10 или 20 или 50 несортированных элементов – я действительно не хочу повторять каждый набор, чтобы узнать, сколько работы это будет!

Вместо этого, давайте попробуем и посмотрим, сможем ли мы найти шаблон и сделать некоторые абстракции о том, сколько итераций, которые нам придется сделать с помощью массива n элементы.

Обобщение количества итерации для пузыря

Мы можем начать с простого примера. С несопоставленным списком всего 2 числа нам нужно повторить только один раз, поскольку в одном проходе мы сравниваем одну пару, которая составляет список.

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

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

В целом, учитывая коллекцию N несортированных элементов, он проходит (N-1) итерации через список, чтобы сортировать его, используя алгоритм сортировки пузырьков.

Это обобщение может быть супер полезным для нас, когда нам даны большие массивы, и мы хотим знать, сколько раз нам нужно повторить его, если мы планируем на использование Bubble Worth в качестве нашего сортировки алгоритма.

Оптимальный пузырь

Теперь, когда мы видели один шаблон в сортировке пузыря, его тоже немного легче поймать пару других. Есть одна характеристика пузыря, которая действительно интересна – и это на самом деле причина, по которой Bubble Sort получил это имя!

Давайте посмотрим на пример, начиная с несортированного массива:

Что ставит пузырь в пузырь?

В этом примере каждая итерация отвечает за перемещение самого большого несортированного элемента в его правильное место в массиве. Например, первая итерация эффективно перемещает наибольшее количество, 12, до конца списка. Вторая итерация перемещает второе по величине число (или, крупнейшее царствование число), 9, до его правильного места в списке.

Это то, что дает пузырем сортировать свое название: самые большие номера начинают «пузырить до конца списка, где они принадлежат.

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

Мы также можем увидеть другой Узор здесь тоже! Обратите внимание, как нам не нужно было сравнивать последние два элемента, 9 и 12, во второй итерации; Они были эффективно уже отсортированы с нашего первого прохода через массив.

После X iTerations, проверка последних х элементов избыточно

Давайте постараемся обобщить этот шаблон снова и попытаться найти правило, которое мы следуем.

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

Если бы мы написали третью итерацию, мы увидим, что в конечном итоге мы получим [3, 1, 8, 9, 12] на третьем проходе, и последние три элемента отсортировали. Это означает, что нам не нужно проверить последние три элемента.

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

После X итераций проверка последних X -элементов в коллекции является избыточной.

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

Теперь, когда мы очень внимательно смотрели на Bubble Sort, мы можем сделать некоторые более крупные обобщения об этом алгоритме.

Основы сортировки пузыря

Удобная вещь, которую нужно помнить о Bubble Sort, состоит в том, что единая итерация ставит один элемент (обычно самый большой unsorted элемент) в правильном месте в массиве. Также приятно иметь в виду, что это займет (N-1) проходит через коллекцию, где n Это общее количество элементов, чтобы сортировать всю вещь.

Сколько пузырьков слишком много пузырьков?

Хорошо, нам пора говорить о слоне (дует пузыри) в комнате: неэффективность пузырька. Я не буду лгать тебе – это определенно медленно и неэффективно. Но я не рекомендую вам просто принять мое слово для этого. Вместо этого давайте выясним Почему Это медленно и неэффективно, вместе!

Я думаю, что лучший способ на самом деле на самом деле увидеть скорость и эффективность алгоритма сортировки пузырьков – это реализация, а затем запущена его. Вот моя реализация Bubble Sort, основанная на коде Rosetta JavaScript версия , который я модифицировал:

function bubbleSort(array) {
  var isSorted = false;

  while (!isSorted) {
    isSorted = true;

// Iterate until we get to the last element
    for (var index = 1; index < array.length; index++) {
      console.log("comparing " + array[index] + " and " + array[index - 1]);

      // If the element to the left is bigger, then swap the element
      // that we're currently looking at with its left neighbor.
      if (array[index - 1] > array[index]) {
        isSorted = false;

console.log("SWAPPING " + array[index] + " and " + array[index - 1]);

        // Swap elements by creating a temporary reference.
        var temporaryReference = array[index - 1];
        array[index - 1] = array[index];
        array[index] = temporaryReference;
      }

console.log('array is now ', array);
    }

console.log(" **one full pass through array**");
    console.log("***is array sorted? ", isSorted);
  }

  return array;
}

Я добавил некоторую консоль. ЛОГ, чтобы помочь нам посмотреть, что на самом деле происходит здесь. Если вам любопытно, вы можете запустить этот алгоритм самостоятельно, используя консоль JavaScript в вашем браузере! Для наших целей мы будем использовать тот же массив, с которого мы начали в начале этой статьи: [9, 7, 4, 1, 2].

var myArray = [9, 7, 4, 1, 2];

bubbleSort(myArray);

Когда мы называем нашу функцию Bublyort, вот что отображается в консоли:

> comparing 7 and 9
> SWAPPING 7 and 9
> array is now (5) [7, 9, 4, 1, 2]
> comparing 4 and 9
> SWAPPING 4 and 9
> array is now (5) [7, 4, 9, 1, 2]
> comparing 1 and 9
> SWAPPING 1 and 9
> array is now (5) [7, 4, 1, 9, 2]
> comparing 2 and 9
> SWAPPING 2 and 9
> array is now (5) [7, 4, 1, 2, 9]
> **one full pass through array**
> ***is array sorted? false
> comparing 4 and 7
> SWAPPING 4 and 7
> array is now (5) [4, 7, 1, 2, 9]
> comparing 1 and 7
> SWAPPING 1 and 7
> array is now (5) [4, 1, 7, 2, 9]
> comparing 2 and 7
> SWAPPING 2 and 7
> array is now (5) [4, 1, 2, 7, 9]
> comparing 9 and 7
> array is now (5) [4, 1, 2, 7, 9]
> **one full pass through array**
> ***is array sorted? false
> comparing 1 and 4
> SWAPPING 1 and 4
> array is now (5) [1, 4, 2, 7, 9]
> comparing 2 and 4
> SWAPPING 2 and 4
> array is now (5) [1, 2, 4, 7, 9]
> comparing 7 and 4
> array is now (5) [1, 2, 4, 7, 9]
> comparing 9 and 7
> array is now (5) [1, 2, 4, 7, 9]
> **one full pass through array**
> ***is array sorted? false
> comparing 2 and 1
> array is now (5) [1, 2, 4, 7, 9]
> comparing 4 and 2
> array is now (5) [1, 2, 4, 7, 9]
> comparing 7 and 4
> array is now (5) [1, 2, 4, 7, 9]
> comparing 9 and 7
> array is now (5) [1, 2, 4, 7, 9]
> **one full pass through array**
> ***is array sorted? true
>> (5) [1, 2, 4, 7, 9]

Вау, это был много . Давайте посмотрим на то, что здесь происходит. Мы видим, что алгоритм делает именно то, что мы делаем, когда мы вытянули каждую итерацию – это просто делает это быстрее, чем нас! Мы видим это сравнение двух элементов одновременно. Если мы ищем экземпляры ** один полный проход через массив * * Мы можем увидеть, как выглядит массив в конце одной итерации. Учитывая тот факт, что этот массив имеет только пять элементов в нем, что нужно отсортировать, в настоящее время есть 16 сравнений здесь. Это кажется … не очень здорово.

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

Есть еще одна проблема: что, если наш список уже отсортирован? Наивная реализация Bubble Sort будет выполнять весь список, даже если бы она была отсортирована, и использовать много времени и памяти для этого.

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

Тем не менее, есть один Легкая вещь, которую мы можем сделать, чтобы избежать этого сумасшедшего повторения ненужной работы. Мы можем проверить и посмотреть, делаем ли мы какие -либо изменения в нашей первой итерации; Если мы не можем, мы знаем, что список должен быть отсортирован, и мы можем остановить итерацию.

Если мы оглянемсь назад на нашу реализацию JavaScript, мы заметим, что мы на самом деле делаем именно это! Испортированная переменная выполняет как флаг, который мы устанавливаем, когда мы начнем итацию.

var isSorted = false;

isSorted = true;

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

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

Насколько плохой это пузырь, ровно?

Если пузырь сорта плохо, мы, вероятно, должны выяснить просто Как Плохо это. Мы знаем, что мы должны сделать n Количество итераций через массив n Общие элементы для того, чтобы сортировать его. Мы также знаем, что в каждой итерации мы должны проверить все n Элементы в массиве.

Умножение будет сообщать нам, что если мы идете через все n Элементы и в каждой итерации, проверка всех n Элементы, мы в основном умножаем n x n , что это Отказ

В контексте сложности времени мы могли бы сказать, что большая O обозначение алгоритма сортировки пузырьков является O (n²) Отказ

На основании того, что мы узнали в посте прошлой недели на Сортировка отбора , мы также знаем, есть ли у нас петля вложенный внутри другой петли в алгоритме, это хороший показатель, что большая o обозначения алгоритма будет квадратичный . То есть, поскольку наш массив удваивается в размерах, количество времени, которое нам потребуется, чтобы разобраться через него Четырехместный Отказ

Тем не менее, похоже на сортировку отбора, Bubble Sort имеет квадратичную сложность времени, но A Константа (или, O (1) ) Сложность космического пространства.

Давайте посмотрим на некоторые другие способы, которыми сортировки пузырьков складываются к другим алгоритмам, на которые мы уже смотрели, используя классификации, которые мы Уже узнал о Отказ

Как сортирует пузырь?

Мы знаем, что сложность времени пузырьков – квадратичный или O (n²), в больших обозначении. Bubble Worth не требует много дополнительной памяти, когда она работает – ему нужна только несколько указателей за раз, чтобы поддерживать ссылку на пары, на которые он смотрит, и, возможно, замена (например, в нашем коде, временное действие переменная). Поскольку он требует только O (1) постоянного пространства, мы можем сказать, что это вообще алгоритм , который работает непосредственно на входных данных.

Bubble Sort также является стабильный алгоритм, что означает, что он сохраняет относительный порядок элементов. Если мы думаем об этом, это имеет смысл: представьте себе массив с двумя экземплярами числа: [4, 2, 3, 3]. При сравнении двух экземпляров 3, алгоритм не поменятся им, если тот, который слева не больше, чем тот справа. Таким образом, их относительный порядок останется прежним.

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

Наконец, мы уже уверены, что Bubble Sort – это оба нерешительный (и вместо этого, итеративно), и Сравнение Сортировка, поскольку по определению это итерации через массив и сравнивает два элемента за раз.

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

Кажется, все знают, что сортировка пузыря, как правило, плохие новости – даже Барак Обама знал, что когда он был сенатором в 2008 году:

Но угадайте, что? Теперь ты знаешь Почему Это плохое представление, как оптимизировать ее и как говорить кого-то другого из этого. Надеюсь, вам никогда не придется делать это, хотя!

Ресурсы

Потому что пузырь – это такой печально известно Алгоритм, есть много чтения, что вы можете сделать на этом. Тем не менее, я нашел видео, чтобы быть особенно полезным для этого алгоритма, поскольку они действительно помогают иллюстрировать «пузырь, который происходит. Я включил несколько хороших в ссылках ниже. Счастливый пузырь!

  1. Сорта пузыря , Интерактивный Python
  2. Сортировка алгоритмов/пузырь Сортировка С Код Розетта
  3. Алгоритмы: пузырь Сортировка , Хакерарь
  4. Алгоритм сортировки пузырьков , mycodeschool
  5. Сортировка пузыря С Гарвард CS50.

Этот пост был первоначально опубликован на medium.com

Оригинал: “https://dev.to/vaidehijoshi/bubbling-up-with-bubble-sorts”