Сортування вставки проти алгоритмів сортування міхурів


85

Я намагаюся зрозуміти кілька алгоритмів сортування, але я намагаюся побачити різницю в алгоритмі сортування бульбашок та вставки.

Я знаю, що обидва є O (n 2 ), але мені здається, що сортування міхурів просто пускає максимальне значення масиву вгору для кожного проходу, тоді як сортування вставки просто опускає найнижче значення до нижнього кожного проходу. Хіба вони не роблять однаково, але в різних напрямках?

Для сортування при вставці кількість порівнянь / потенційних свопів починається з нуля і щоразу збільшується (тобто 0, 1, 2, 3, 4, ..., n), але для сортування за допомогою бульбашок така сама поведінка трапляється, але в кінці сортування (тобто n, n-1, n-2, ... 0), оскільки сортування за допомогою міхура більше не потрібно порівнювати з останніми елементами, оскільки вони сортуються.

Однак при всьому цьому видається консенсусом, що сортування вставки взагалі краще. Хтось може сказати мені, чому?

Редагувати: Мене в першу чергу цікавлять відмінності в тому, як працюють алгоритми, не стільки їх ефективність чи асимптотична складність.


1
Це добре задокументовано в інших місцях: див., Наприклад, en.wikipedia.org/wiki/Sorting_algorithm . Тут скопіювати безглуздо, і хороша відповідь буде просторою.
Вірсавія,

@Bathsheba 75 людей, які проголосували і 88 тис. Людей, які переглянули це питання, схоже, не згодні; )
синтаксичний аналізатор

@parsecer: Ха! Тепер мені доведеться переглянути відповіді. Поточна відповідь з найвищим рейтингом корисна; не впевнений в інших. Ось деякі реп-бали, втрачені при відмові. Твердження "Ось чому сортування вставки швидше сортування за міхурами" у прийнятій відповіді не обов'язково відповідає дійсності.
Вірсавія

@Bathsheba О ні
парсер

Відповіді:


38

У сортуванні за допомогою міхура в i-тій ітерації у вас є внутрішні ітерації ni-1 (n ^ 2) / 2 загалом, але в сортуванні вставки у вас є максимум iтерацій i на i-му кроці, але i / 2 в середньому, оскільки ви можете зупинити внутрішній цикл раніше, після того, як ви знайшли правильне положення для поточного елемента. Отже, у вас є (сума від 0 до n) / 2, яка дорівнює (n ^ 2) / 4;

Ось чому сортування вставки відбувається швидше, ніж сортування за допомогою міхура.


2
Пояснення алгоритму є в мережі всюди, я думаю.
sasha.sochka

3
так, але, схоже, ОП все ще не
вловлює

15
Ну, можна сказати, я розумію основи . Я хотів порівняння, і це справді непогано. Отже, ідея полягає в тому, що в той час як сортування вставки змушує i-й елемент опускатися вниз, а сортування міхура змушує його пузиритися, сортування вставки не змушує його опускатися до самого дна, воно просто призводить до того, що він опускається в потрібне положення в вже відсортований розділ. Таким чином, це робить менше порівнянь / обмінів. Це так?
Migwell

1
Що? "Отже, у вас є (сума від 0 до n) / 2, яка дорівнює (n ^ 2) / 4 усього" Для цього потрібні деякі expl, будь ласка! 0 + 1 + 2 + 3 + 4 + 5 = 15; 15/2 = 7,5; 7,5 * 4 = 30; sqrt (30) = безглуздя
Джон Сміт

@JohnSmith Я вважаю, що у відповіді є невелика помилка. Сума від 1 до n дорівнює n * (n + 1) / 2, оскільки це трикутне число. Знайдіть трикутне число, щоб отримати додаткові пояснення. Отже, поділене на 2 - це просто n * (n + 1) / 2.
CognizantApe

122

Сортування вставки

Після того, як я ітерація першого I елементи впорядковані.

У кожній ітерації наступний елемент пропускається через відсортований розділ, поки не досягне потрібного місця:

sorted  | unsorted
1 3 5 8 | 4 6 7 9 2
1 3 4 5 8 | 6 7 9 2

4 потрапляє у відсортований розділ

Псевдокод:

for i in 1 to n
    for j in i downto 2
        if array[j - 1] > array[j]
            swap(array[j - 1], array[j])
        else
            break

Сортування бульбашок

Після того, як я ітерація останніх I елементи є найбільшими, і наказали.

У кожній ітерації перебирайте невідсортований розділ, щоб знайти максимум.

unsorted  | biggest
3 1 5 4 2 | 6 7 8 9
1 3 4 2 | 5 6 7 8 9

5 виводиться з несортованого розділу

Псевдокод:

for i in 1 to n
    for j in 1 to n - i
         if array[j] > array[j + 1]
             swap(array[j], array[j + 1])

Зверніть увагу, що типові реалізації завершуються достроково, якщо під час однієї з ітерацій зовнішнього циклу не виконується обмін (оскільки це означає, що масив відсортований).

Різниця

При вставці елементи сортування виділяються з сортуванням в розділ сортування, тоді як при сортуванні за допомогою міхурів максимуми виводяться з несортованого розділу.


10
Дякую, це дуже ясно! Я думаю, головне, що мені потрібно було виділити, - це те, що оператор break в Insertion Sort означає, що він може закінчити кожну ітерацію достроково: тобто коли він знайшов свою позицію в відсортованому розділі. Сортування за допомогою міхура вимагає продовження обміну, доки найбільший елемент у несортованому розділі досягне відсортованого розділу, тому ніколи не припиняється достроково. Хоча це фантастичний підсумок, тому +1
Мігвелл

4
Я думаю, що це повинна бути найкраща відповідь :)
Аделін

2
Плюс 1 для наочності, дидактичного значення та для основних інваріантів циклу кожного алгоритму. Шкода, що він не містить явно порівняння складності (вираженої як функція від n ), у будь-якому випадку я вважаю це кращою відповіддю, ніж прийнята, оскільки з цього я бачу різницю.
Хонза Зідек,

Чи можу я запитати, чому ви на кожному кроці замінюєте свій товар у коді псевдо вставки? якщо (a [j-1]> a [j]), тоді a [j] = a [j-1] Інакше якщо (a [j-1] <e && a [j]> e), ніж a [j] = e; перерва; , де e - елемент, який потрібно відсортувати. За допомогою цього рішення ви не поміняєте місцями вже відсортовані елементи, а просто скопіюєте їх. З нетерпінням чекаю пояснень, оскільки я трохи розгублений.
Каролі

@Karoly, я вибрав свою версію, оскільки вона простіша. Ваш трохи швидший, добре, що ви на це вказуєте. Вікіпедія описує обидві версії.
том

16

Ще однієї різниці я тут не бачив:

Бульбове сортування має 3 присвоєння значень на підкачку : спочатку потрібно створити тимчасову змінну, щоб зберегти значення, яке потрібно просунути вперед (№1), а потім записати іншу змінну підкачки у те місце, де ви щойно зберегли значення (№2), а потім вам потрібно записати свою тимчасову змінну в іншому місці (№3). Ви повинні зробити це для кожного місця - ви хочете йти вперед - щоб відсортувати свою змінну до правильного місця.

За допомогою вставки сортування ви поміщаєте свою змінну для сортування за тимчасовою змінною, а потім ставите всі змінні перед цією плямою на 1 місце назад, до тих пір, поки ви досягнете правильної точки для вашої змінної. Це робить 1 присвоєння вартості на пляму . Врешті-решт ви пишете свою змінну temp на місці.

Це також робить набагато меншу цінність.

Це не найсильніша швидкісна вигода, але я думаю, що це можна згадати.

Сподіваюся, я висловив себе зрозумілим, якщо ні, то вибачте, я не рідна Британія


1
"а потім поставити всі змінні перед цією плямою на 1 місце назад" - і чи не потрібне це також для завантаження призначень для зсуву даних? (припускаючи, що дані в будь-якому випадку зберігаються суміжно, а не у зв’язаному списку)
Mark K Cowan

@MarkKCowan, так, саме тут сортування вставки робить присвоєння за "плямою", як висловився вищевказаний користувач. В основному, сортування вставки можна записати з одним призначенням у внутрішній цикл, тоді як у сортувальних сортів - 3 призначення у внутрішньому циклі.
JSQuareD

9

Основною перевагою сортування вставки є те, що це онлайн-алгоритм. Не потрібно мати усіх значень на початку. Це може бути корисно при роботі з даними, що надходять з мережі, або з якогось датчика.

У мене відчуття, що це було б швидше, ніж інші звичайні n log(n)алгоритми. Оскільки складність полягала б, n*(n log(n))наприклад, у зчитуванні / зберіганні кожного значення з потоку ( O(n)), а потім у сортуванні всіх значень ( O(n log(n))), в результаті чогоO(n^2 log(n))

Навпаки, використання Insert Sort потребує O(n)зчитування значень з потоку і O(n)для того, щоб поставити значення у правильне місце, отже це O(n^2)лише. Інша перевага полягає в тому, що вам не потрібні буфери для зберігання значень, ви сортуєте їх за кінцевим пунктом призначення.


Якщо це нормально, якщо обхід даних за порядком є ​​чимось іншим, ніж простим скануванням масиву, ви можете сортувати на льоту набагато ефективніше. наприклад, вставляти елементи у двійкове дерево під час їх отримання. Це дає вам O(n log(n))загальну виконану роботу, щоб мати відсортовану колекцію на кожному кроці. (Обхід в порядку в будь-якій точці є O(m)). Якщо вам просто потрібен відсортований результат в кінці, але ви хочете перекрити обчислення сортування з часом передачі даних, Купа може бути непоганою. (І працює на місці, як вставка-сортування).
Пітер Кордес,

У будь-якому випадку, ні сортування за бульбашками, ні вставка-сортування не є ідеальними для цього, оскільки розміри проблем досить великі, щоб O(f(n))клас складності мав значення більше, ніж деталі реалізації та постійні фактори.
Пітер Кордес,

Виправлення: купа не підходить для цього. Він виконує більшу частину роботи з сортування, коли ви вилучаєте елементи у відсортованому порядку, тому вирощування настільки дешеве. Мета тут полягає в тому, щоб виконати більшу частину роботи до моменту надходження останнього елемента.
Пітер Кордес,

У будь-якому випадку, якщо вам потрібно було підтримувати відсортований масив для nвставок, то насправді це зводиться до того, який алгоритм найкраще підходить для сортування майже відсортованого масиву, де вгорі є один невідсортований елемент. Багато O(n log(n))алгоритмів сортування є O(n)майже відсортованими, тому неправда, що вам потрібна була sum(M=1..n, O(M * log(M)) )робота. Це справді було б O(n^2 log(n)), але при правильному виборі алгоритму вони будуть цілком O(n^2)працювати. Однак для цього найефективніше вставка-сортування.
Пітер Кордес,

7

Bubble Sort відсутній в Інтернеті (він не може сортувати потік вхідних даних, не знаючи, скільки буде елементів), оскільки він насправді не відстежує загальний максимум відсортованих елементів. Коли елемент вставлений, вам потрібно буде почати бульбашку з самого початку


4

ну сортування бульбашок краще сортування вставкою лише тоді, коли хтось шукає найкращі k елементи з великого списку числа, тобто в сортуванні бульбашок після k ітерацій ви отримаєте найкращих k елементів. Однак після k ітерацій при сортуванні вставки це лише гарантує, що ці k елементи сортуються.


2

Хоча обидві сорти мають значення O (N ^ 2). Приховані константи набагато менші в Insertion sort. Приховані константи стосуються фактичної кількості виконуваних примітивних операцій.

Коли сортування вставки має кращий час роботи?

  1. Масив майже сортується - зауважте, що вставка сортування в цьому випадку робить менше операцій, ніж сортування за допомогою міхура.
  2. Масив має порівняно невеликий розмір: за допомогою вставки ви переміщуєте елементи навколо поточного елемента. Це краще, ніж сортування за допомогою міхура, якщо кількість елементів невелика.

Зверніть увагу, що сортування вставки не завжди краще сортування за допомогою міхура. Щоб отримати найкраще з обох світів, ви можете використовувати сортування вставки, якщо масив має невеликий розмір, і, можливо, об'єднати сортування (або швидку сортування) для більших масивів.


2
Якби кількість елементів не мала, як було б краще сортувати бульбашки? Я розумію, що пересування слайдів у IS чи обмін місцями в BS залежатиме від того, чи буде порівнюваний елемент більшим (IS) чи меншим (BS), а не від # елементів. Будь ласка, виправте мене, якщо помилився.
Мустафа

0

Сортування бульбашок практично марно за будь-яких обставин. У випадках використання, коли сортування вставки може мати занадто багато свопів, можна використовувати сортування виділення, оскільки воно гарантує менше N разів свопу. Оскільки сортування виділення краще сортування за допомогою міхура, сортування за допомогою міхура не має випадків використання.


0

Кількість свопів у кожній ітерації

  • Insertion-sort робить щонайбільше 1 підкачку в кожній ітерації .
  • Bubble-sort робить від 0 до n обмінів у кожній ітерації.

Доступ та зміна відсортованої частини

  • Вставлення-сортування отримує доступ (і за потреби змінюється) до відсортованої частини, щоб знайти правильне положення числа, що розглядається.
  • При оптимізації Bubble-сортування не отримує доступу до того, що вже відсортовано.

Інтернет чи ні

  • Insertion-sort знаходиться в Інтернеті. Це означає, що Insertion-sort приймає по одному вводу за раз, перш ніж ставить у відповідне положення. Він не повинен порівнювати лише adjacent-inputs.
  • Сортування за бульбашками не в Інтернеті. Він не працює за один вхід за раз. Він обробляє групу входів (якщо не всі) у кожній ітерації. Сортування за бульбашками лише порівняння та обмін місцямиadjacent-inputs в кожній ітерації.

0

вставка сортування:

1.У вставці не потрібно замінювати сортування.

2. складність часу вставки сортує Ω (n) для найкращого випадку та O (n ^ 2) найгіршого випадку.

3. менш складний у порівнянні з сортом бульбашок.

4. приклад: вставити книги в бібліотеку, розкласти картки.

сортування міхурів: 1. у сортуванні міхурів потрібно замінити.

2. часова складність сортування бульбашок становить Ω (n) для найкращого випадку та O (n ^ 2) найгіршого випадку.

3. більш складний у порівнянні з вставним сортуванням.


1
Як так, обмін не потрібен? Він міняє місцями елементи, щоб перевести елемент у правильне положення. І я б не сказав, що сортування бульбашок є більш складним.
синтаксичний аналізатор

-1

Сортування вставки можна відновити як " Шукайте елемент, який повинен бути в першій позиції (мінімальній), звільніть місце, перемістивши наступні елементи, і поставте його на перше місце. Добре. Тепер подивіться на елемент, який повинен бути на 2-му. ... "і так далі ...

Сортування за допомогою бульбашок працює по-різному, що можна відновити, якщо « поки я знайду два сусідні елементи, які знаходяться в неправильному порядку, я поміняю місцями ».


Це дійсно допомагає із сортуванням вставки, але ваше пояснення сортування бульбашок не включає фактичні цикли, тому я не можу насправді порівняти їх. Я вставки сортування також ефективно має правило Поки я знаходжу два сусідні елементи, які знаходяться в неправильному порядку, я поміняю їх місцями , це те, як працюють цикли, відрізняється.
Migwell

3
Хіба це не сортування?
harold

О так, це правда ^
Мігвелл
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.