Shell-sorteringsalgoritm med exempel

⚡ Smart sammanfattning

Shell Sort är en jämförelsealgoritm på plats som generaliserar insättningssortering genom att jämföra element som sitter långt ifrån varandra och sedan krympa avståndet tills intilliggande element är sorterade.

  • 📊 Definition: En generalisering av insättningssortering på plats som föreslogs av Donald Shell 1959 som använder en minskande gapsekvens.
  • 🔀 Gapsekvenser: Shells original är n/2, n/4, …, 1; Knuth-, Sedgewick- och Ciura-sekvenserna presterar bättre i praktiken.
  • Komplexitet: O(n log n) bästa fall, O(n^2) värsta fall och O(1) hjälprum.
  • Använd fall: Linuxkärnan, uClibc och bzip2 använder Shell Sort för att undvika rekursion och extra stackminne.
  • 🤖 AI-vinkel: AI-assistenter kan föreslå gapsekvenser och generera animerade Shell Sort-visualiseringar på begäran.

Vad är Shell-sortering?

Shell Sort, även kallad Shells metod, är en effektiv sorteringsalgoritm baserad på jämförelse på plats. Uppkallad efter Donald Shell, som introducerade idén 1959, är det en generaliserad utvidgning av insertion sortering som övervinner dess kvadratiska beteende på spridda data.

Grundtanken är att gruppera element som är långt ifrån varandra, sortera varje grupp med hjälp av insättningssortering och minska gapet steg för steg tills det når ett. Vid det laget är arrayen nästan sorterad.

Detta mellanrum, intervallet, följer en vald sekvens såsom Shells original, Knuths, Hibbards eller Sedgewicks. Shells original är n/2, n/4, ..., 1.

Skalsorteringsalgoritm

Steg 1) Initiera intervallvärdet h = n/2, där n är arrayens storlek.

Steg 2) Placera alla element inom ett avstånd från intervallet h i en dellista.

Steg 3) Sortera varje dellista med hjälp av insättningssortering.

Steg 4) Sätt ett nytt intervall h = h/2.

Steg 5) Om h > 0, återgå till steg 2. Annars, gå till steg 6.

Steg 6) Den resulterande arrayen är nu helt sorterad.

Hur Shell Sortering fungerar

Vid insättningssortering flyttas elementen endast en position åt gången. Shell Sort delar istället upp arrayen i dellistor med brett mellanrum baserat på intervallet och kör insättningssortering på varje dellista.

Allt eftersom intervallet krymper, växer dellistan. Eftersom tidigare intervall lämnar data delvis sorterade, kräver kortare intervall betydligt färre byten än att köra insättningssortering från grunden. Figuren nedan illustrerar ett Shell Sort-pass.

Skalsortering fungerar

Funktionssätt för Shell Sort-algoritmen med exempel

Låt oss sortera arrayen nedan med hjälp av Shell Sort.

Arbetar med Shell Sort Algorithm

Steg 1) Arraystorleken är 8, så det initiala intervallvärdet är h = 8/2 = 4.

Steg 2) Gruppera element fyra positioner ifrån varandra. Dellistor: {8, 1}, {6, 4}, {7, 5}, {2, 3}.

Arbetar med Shell Sort Algorithm

Steg 3) Sortera varje dellista med hjälp av insättningssortering. En temporär variabel håller det värde som placeras medan elementen flyttas. Efter bytena ser arrayen ut så här.

Arbetar med Shell Sort Algorithm

Steg 4) Minska intervallet. Det nya intervallet är h = 4/2 = 2.

Steg 5) Eftersom 2 > 0, återgå till steg 2 och gruppera elementen två positioner ifrån varandra: {1, 5, 8, 7} och {4, 2, 6, 3}.

Arbetar med Shell Sort Algorithm

Sortera den första dellistan. Arrayen blir:

Arbetar med Shell Sort Algorithm

Efter sortering av den andra dellistan:

Arbetar med Shell Sort Algorithm

Minska intervallet igen till h = 2/2 = 1. Med ett mellanrum på ett kör Shell Sort en sista insättningssorteringsprocess över hela arrayen, som visas nedan.

Arbetar med Shell Sort Algorithm

Arbetar med Shell Sort Algorithm

Arbetar med Shell Sort Algorithm

Steg 6) Att dividera intervallet igen ger 0. Arrayen är nu helt sorterad:

Arbetar med Shell Sort Algorithm

Pseudo-Code för Shell-sortering

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

Skalsorteringsprogram i C/C++

Ingång:

//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";
}

Produktion:

Sorted Output:

1 2 3 4 5 6 7 8

Skalsorteringsexempel i Python

Ingång:

#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)

Produktion:

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

Tillämpningar av Shell Sort

Shell Sort förekommer fortfarande i moderna system där stackutrymme eller enkelhet är viktigt.

  • Ocuco-landskapet Linuxkärnan använder Shell Sort på platser där det är viktigt att undvika en anropsstack.
  • uClibc inbäddade C-bibliotek använder Shell Sort för att hålla minnesanvändningen låg.
  • bzip2 använder Shell Sort för att undvika djup rekursion under blocksortering.
  • Inbäddad firmware gynnar Shell Sort för små datamängder där rekursion är begränsad.

Fördelar och nackdelar med skalsortering

Fördelar Nackdelar
Ingen anropsstack krävs, vilket är idealiskt för inbyggda system. Inte det snabbaste alternativet för mycket stora arrayer.
Lätt att implementera med en liten mängd kod. Prestandan försämras på data med vitt spridda element.
Effektiv för matriser av måttlig storlek eller delvis sorterade matriser. Värsta tänkbara tidskomplexitet är känslig för den valda gapsekvensen.
Fungerar på plats, så den använder konstant hjälpminne. Det är inte en stabil sortering, så lika nycklar kan ändra relativ ordning.

Skalsorteringskomplexitetsanalys

Tidskomplexitet för skalsortering

Tidskomplexiteten för Shell Sort beror på vilken gapsekvens som används.

I bästa fall, när arrayen redan är nästan arrangerad, behöver varje genomgång endast ett logaritmiskt antal tester, vilket ger O(n log n).

I värsta fall är arrayen arrangerad så att elementen behöver maximalt antal jämförelser, och det slutliga inkrementet dominerar vid O(n^2) med Shells ursprungliga sekvens.

  1. Bästa tänkbara komplexitet: O(n log n)
  2. Genomsnittlig komplexitet i fallet: O(n log n) till O(n^(4/3)) beroende på gapsekvensen
  3. Värsta tänkbara komplexitet: O(n^2) med Shells ursprungliga sekvens

Den bästa generella gapsekvensen är fortfarande en öppen forskningsfråga, även om Sedgewick- och Ciura-sekvenser fungerar väl i praktiken.

Skalsortering Space Complexity

Shell Sort kräver inga hjälpmatriser, så rymdkomplexiteten är O(1) oavsett inmatningsstorlek, vilket är en av dess starkaste praktiska fördelar.

Vanliga frågor

Shell Sort är en algoritm för jämförelsesortering på plats som föreslogs av Donald Shell 1959. Den generaliserar insättningssortering genom att jämföra element som är långt ifrån varandra och sedan krympa gapet tills intilliggande element är sorterade, vilket dramatiskt minskar antalet byten.

Den bästa tidskomplexiteten är O(n log n), och den värsta komplexiteten är O(n^2) med Shells ursprungliga sekvens. Bättre gapsekvenser som Sedgewicks reducerar det värsta fallet till ungefär O(n^(4/3)). Rymdkomplexiteten är O(1).

Nej, Shell Sort är inte stabil. Eftersom element jämförs och byts ut över stora mellanrum kan två lika nycklar ändra relativ ordning under ett pass. Om stabilitet är viktigt, använd merge sorter eller en stabil variant av insertion sorter istället.

Insättningssortering flyttar element en position i taget. Shell Sort jämför först element som är långt ifrån varandra och krymper sedan gradvis mellanrummet. Resultatet är en nästan sorterad array när mellanrummet når ett, så den sista insättningssorteringen avslutas mycket snabbt.

AI-assistenter kan analysera din datauppsättnings storlek, distribution och begränsningar och sedan rekommendera en algoritm som Shell Sort, Quicksort eller Radix Sort. De kan också generera benchmark-skript som jämför körtid och minnesanvändning så att du kan validera rekommendationen på verkliga arbetsbelastningar.

Ja. AI-verktyg kan generera animerade visualiseringar av Shell Sort som markerar gapgrupper, jämförelser och swaps i realtid. Sådana visualiseringar hjälper elever att se hur intervallet krymper och hur arrayen konvergerar mot ett sorterat tillstånd, pass efter pass.

Sammanfatta detta inlägg med: