Алгоритъм за сортиране по Shell с пример

⚡ Умно обобщение

Shell Sort е алгоритъм за сравнение на място, който обобщава сортирането с вмъкване, като сравнява елементи, които са разположени далеч един от друг, след което свива разстоянието, докато съседните елементи бъдат сортирани.

  • 📊 Определение: Обобщение на място на сортирането чрез вмъкване, предложено от Доналд Шел през 1959 г., което използва намаляваща последователност от празнини.
  • 🔀 Последователности на пропуските: Оригиналът на Шел е n/2, n/4, …, 1; последователностите на Кнут, Седжуик и Чиура се представят по-добре на практика.
  • Сложност: O(n log n) най-добър случай, O(n^2) най-лош случай и O(1) спомагателно пространство.
  • Случаи на употреба: Ядрото на Linux, uClibc и bzip2 използват Shell Sort, за да избегнат рекурсия и допълнителна памет в стека.
  • 🤖 Ъгъл на изкуствен интелект: Асистентите с изкуствен интелект могат да предлагат последователности от празнини и да генерират анимирани визуализации на сортиране по Shell при поискване.

Какво е сортиране по Shell?

Сортирането по Шел, наричано още метод на Шел, е ефикасен алгоритъм за сортиране, базиран на сравнение на място. Наречен на името на Доналд Шел, който въвежда идеята през 1959 г., той е обобщено разширение на сортирането чрез вмъкване, което преодолява квадратичното му поведение върху разпръснати данни.

Основната идея е да се групират елементи, които са отдалечени един от друг, да се сортира всяка група чрез сортиране с вмъкване и да се свива разстоянието стъпка по стъпка, докато достигне единица. До този момент масивът е почти сортиран.

Тази празнина, интервалът, следва избрана последователност, като например оригиналната на Шел, на Кнут, на Хибард или на Седжуик. Оригиналът на Шел е n/2, n/4, ..., 1.

Алгоритъм за сортиране на Shell

Стъпка 1) Инициализирайте интервалната стойност h = n/2, където n е размерът на масива.

Стъпка 2) Поставете всички елементи в рамките на разстояние от интервала h в подсписък.

Стъпка 3) Сортирайте всеки подсписък, използвайки сортиране с вмъкване.

Стъпка 4) Задайте нов интервал h = h/2.

Стъпка 5) Ако h > 0, върнете се към стъпка 2. В противен случай преминете към стъпка 6.

Стъпка 6) Полученият масив вече е напълно сортиран.

Как работи Shell Sort

При сортирането с вмъкване, елементите се местят само с една позиция наведнъж. Shell Sort вместо това разделя масива на широко разположени подсписъци въз основа на интервала и изпълнява сортиране с вмъкване за всеки подсписък.

С намаляването на интервала, размерът на подсписъка нараства. Тъй като по-ранните преминавания оставят данните частично сортирани, по-малките интервали изискват много по-малко размени, отколкото изпълнението вмъкване сортиране от нулата. Фигурата по-долу илюстрира един проход на сортиране по Shell.

Shell Sort работи

Работа на алгоритъма за сортиране по Shell с пример

Нека сортираме масива по-долу, използвайки Shell Sort.

Работа на алгоритъма за сортиране на Shell

Стъпка 1) Размерът на масива е 8, така че началната стойност на интервала е h = 8/2 = 4.

Стъпка 2) Групирайте елементите на четири позиции една от друга. Подсписъци: {8, 1}, {6, 4}, {7, 5}, {2, 3}.

Работа на алгоритъма за сортиране на Shell

Стъпка 3) Сортирайте всеки подсписък, използвайки сортиране чрез вмъкване. Временна променлива съхранява поставената стойност, докато елементите се изместват. След разместването, масивът изглежда така.

Работа на алгоритъма за сортиране на Shell

Стъпка 4) Намалете интервала. Новият интервал е h = 4/2 = 2.

Стъпка 5) Тъй като 2 > 0, върнете се към стъпка 2 и групирайте елементите на две позиции една от друга: {1, 5, 8, 7} и {4, 2, 6, 3}.

Работа на алгоритъма за сортиране на Shell

Сортирайте първия подсписък. Масивът става:

Работа на алгоритъма за сортиране на Shell

След сортиране на втория подсписък:

Работа на алгоритъма за сортиране на Shell

Намалете интервала отново до h = 2/2 = 1. С интервал от едно, Shell Sort изпълнява последен цикъл на сортиране с вмъкване върху целия масив, както е показано по-долу.

Работа на алгоритъма за сортиране на Shell

Работа на алгоритъма за сортиране на Shell

Работа на алгоритъма за сортиране на Shell

Стъпка 6) Деленето на интервала отново дава 0. Масивът вече е напълно сортиран:

Работа на алгоритъма за сортиране на Shell

псевдо-Code за сортиране по Shell

Start
Input array a of size n
for (interval = n / 2; interval > 0; interval /= 2)
    for (i = interval; i < n; i += 1)
        temp = a[i];
        for (j = i; j >= interval && a[j - interval] > temp; j -= interval)
            a[j] = a[j - interval];
        a[j] = temp;
End

Програма за сортиране на Shell в C/C++

Вход:

//Shell Sort Program in C/C++
#include <bits/stdc++.h>
using namespace std;
void ShellSort(int data[], int size) {
    for (int interval = size / 2; interval > 0; interval /= 2) {
        for (int i = interval; i < size; i += 1) {
            int temp = data[i];
            int j;
            for (j = i; j >= interval && data[j - interval] > temp; j -= interval) {
                data[j] = data[j - interval];
            }
            data[j] = temp;
        }
    }
}
int main() {
    int data[] = {8, 6, 7, 2, 1, 4, 5, 3};
    int size = sizeof(data) / sizeof(data[0]);
    ShellSort(data, size);
    cout << "Sorted Output: \n";
    for (int i = 0; i < size; i++)
        cout << data[i] << " ";
    cout << "\n";
}

Изход:

Sorted Output:

1 2 3 4 5 6 7 8

Shell Пример за сортиране в Python

Вход:

#Shell Sort Example in Python
def ShellSort(data, size):
    interval = size // 2
    while interval > 0:
        for i in range(interval, size):
            temp = data[i]
            j = i
            while j >= interval and data[j - interval] > temp:
                data[j] = data[j - interval]
                j -= interval
            data[j] = temp
        interval //= 2
data = [8, 6, 7, 2, 1, 4, 5, 3]
ShellSort(data, len(data))
print('Sorted Output:')
print(data)

Изход:

Sorted Output:
[1, 2, 3, 4, 5, 6, 7, 8]

Приложения на Shell Sort

Shell сортирането все още се среща в съвременните системи, където пространството на стека или простотата имат значение.

  • - Linux ядрото използва Shell Sort на места, където избягването на стек от повиквания е от значение.
  • Вградената C библиотека uClibc използва Shell Sort, за да поддържа ниско потребление на памет.
  • bzip2 използва Shell Sort, за да избегне дълбока рекурсия по време на блоково сортиране.
  • Вграденият фърмуер предпочита Shell Sort за малки набори от данни, където рекурсията е ограничена.

Предимства и недостатъци на сортирането по Shell

Предимства Недостатъци
Не се изисква стек за извиквания, което е идеално за вградени системи. Не е най-бързият вариант за много големи масиви.
Лесен за изпълнение с малко количество код. Производителността се влошава при данни с широко разпространени елементи.
Ефективен за масиви със среден размер или частично сортирани масиви. Времевата сложност в най-лошия случай е чувствителна към избраната последователност от празнини.
Работи на място, така че използва постоянна спомагателна памет. Това не е стабилен сорт, така че еднаквите ключове могат да променят относителния си ред.

Анализ на сложността на сортирането на Shell

Времева сложност на Shell Sort

Времевата сложност на Shell Sort зависи от използваната последователност от празнини.

В най-добрия случай, когато масивът е почти подреден, всеки проход изисква само логаритмичен брой тестове, което дава O(n log n).

В най-лошия случай масивът е подреден така, че елементите се нуждаят от максимален брой сравнения, а крайното нарастване доминира при O(n^2) с оригиналната последователност на Shell.

  1. Сложност в най-добрия случай: O(n log n)
  2. Средна сложност на случая: O(n log n) до O(n^(4/3)) в зависимост от последователността от празнини
  3. Сложност в най-лошия случай: O(n^2) с оригиналната последователност на Шел

Най-добрата последователност от празнини с общо предназначение все още е отворен изследователски въпрос, въпреки че последователностите на Седжвик и Чиура се представят добре на практика.

Shell Sort Space Complexity

Shell Sort не изисква спомагателни масиви, така че пространствената сложност е O(1), независимо от размера на входните данни, което е едно от най-силните му практически предимства.

Въпроси и Отговори

Shell Sort е алгоритъм за сортиране на място чрез сравнение, предложен от Доналд Шел през 1959 г. Той обобщава сортирането чрез вмъкване, като сравнява елементи, които са далеч един от друг, след което свива разстоянието, докато съседните елементи бъдат сортирани, което драстично намалява броя на разместванията.

Времевата сложност в най-добрия случай е O(n log n), а сложността в най-лошия случай е O(n^2) с оригиналната последователност на Шел. По-добри последователности с интервали, като тези на Седжуик, намаляват най-лошия случай до около O(n^(4/3)). Пространствената сложност е O(1).

Не, сортирането чрез Shell не е стабилно. Тъй като елементите се сравняват и разменят през големи интервали, два еднакви ключа могат да променят относителния ред по време на преминаване. Ако стабилността е от значение, използвайте сортиране с сливане или стабилен вариант на сортиране с вмъкване.

Сортирането чрез вмъкване премества елементите с една позиция наведнъж. Shell Sort първо сравнява елементи, които са далеч един от друг, след което прогресивно свива разликата. Резултатът е почти сортиран масив, когато разликата достигне единица, така че последният проход на сортирането чрез вмъкване завършва много бързо.

Асистентите с изкуствен интелект могат да анализират размера, разпределението и ограниченията на вашия набор от данни, след което да препоръчат алгоритъм, като например сортиране по Shell, бързо сортиране или радикс сортиране. Те могат също така да генерират скриптове за сравнение, които сравняват времето за изпълнение и използването на памет, така че да можете да валидирате препоръката при реални натоварвания.

Да. Инструментите с изкуствен интелект могат да генерират анимирани визуализации на сортиране по Shell, които подчертават групите с празнини, сравненията и размените в реално време. Такива визуализации помагат на учащите да видят как интервалът се свива и как масивът се сближава към сортирано състояние преминаване след преминаване.

Обобщете тази публикация с: