If you're seeing this message, it means we're having trouble loading external resources on our website.

Jeżeli jesteś za filtrem sieci web, prosimy, upewnij się, że domeny *.kastatic.org i *.kasandbox.org są odblokowane.

Główna zawartość

Analiza sortowania przez wstawianie

Podobnie jak sortowanie przez wybieranie, sortowanie przez wstawianie wykonuje pętle powtórzeń na indeksach tablicy. Wywołuje funkcję insert na elementach o indeksach 1, comma, 2, comma, 3, comma, dots, comma, n, minus, 1. Podobnie jak każde wywołanie funkcji indexOfMinimum zajmuje jakiś czas, zależny od rozmiaru posortowanej podtablicy, tak też dzieje się z każdym wywołaniem funkcji insert. Właściwie, słowo "dzieje się" w poprzednim zdaniu powinno być zastąpione wyrażeniem "może się dziać" i zaraz przekonamy się dlaczego.
Rozważmy najpierw sytuację, w której wywołujemy funkcję insert a wartość elementu, który chcemy wstawić do podtablicy jest mniejsza niż każdy element w tej podtablicy. Na przykład: gdy wstawiamy 0 do podtablicy [2, 3, 5, 7, 11], wtedy każdy element podtablicy musi zostać przesunięty o jedną pozycję w prawo. Ogólnie rzecz biorąc, jeśli wstawiamy do podtablicy z k elementami, może mieć miejsce taka sytuacja, że wszystkie k będą musiały być przesunięte o jedną pozycję. Zamiast liczyć dokładnie ile linijek kodu potrzebujemy, aby porównać element znajdujący się przed kluczem i przesunąć go, przyjmijmy, że jest to stała liczba linii; niech to będzie stała c. Dlatego nawet do c, dot, k linii może zająć sytuacja wstawiania wartości do podtablicy k-elementowej.
Załóżmy, że przy każdym wywołaniu insert wartość wstawiana jest mniejsza od wszystkich elementów w części tablicy na lewo od wartości wstawianej. Za pierwszym wywołaniem insert k, equals, 1. Za drugim razem k, equals, 2. Za trzecim k, equals, 3 i tak dalej aż do końca, gdy k, equals, n, minus, 1. Zatem całkowity czas spędzony na wstawianiu do posortowanej podtablicy wynosi
c, dot, 1, plus, c, dot, 2, plus, c, dot, 3, plus, \@cdots, c, dot, left parenthesis, n, minus, 1, right parenthesis, equals, c, dot, left parenthesis, 1, plus, 2, plus, 3, plus, \@cdots, plus, left parenthesis, n, minus, 1, right parenthesis, right parenthesis .
To jest suma ciągu arytmetycznego rosnącego do wartości n, minus, 1 (zazwyczaj spotyka się notację do n). Korzystając ze wzoru na sumę ciągu arytmetycznego, otrzymujemy całkowity czas spędzony na wstawianiu do posortowanej podtablicy
c, dot, left parenthesis, n, minus, 1, plus, 1, right parenthesis, left parenthesis, left parenthesis, n, minus, 1, right parenthesis, slash, 2, right parenthesis, equals, c, n, squared, slash, 2, minus, c, n, slash, 2 .
W notacji Θ zaniedbujemy wyrazy o niższych rzędach - tutaj c, n, slash, 2 - i współczynniki stałe - tutaj c i 1/2. Otrzymujemy w wyniku oszacowanie czasu pracy sortowania przez wstawianie, w rozpatrywanym przykładzie, \Theta, left parenthesis, n, squared, right parenthesis.
Czy sortowanie przez wstawianie może zająć mniej czasu niż \Theta, left parenthesis, n, squared, right parenthesis? Odpowiedź brzmi: tak. Załóżmy, że mamy tablicę [2, 3, 5, 7, 11], w której posortowaną podtablicę stanowią pierwsze cztery elementy, a my wstawiamy do niej wartość 11. Już w pierwszym sprawdzeniu widzimy, że wartość 11 jest większa od 7, a co za tym idzie, żaden element podtablicy nie będzie musiał być przesunięty w prawo. Wtedy wywołanie funkcji insert zajmuje po prostu stałą ilość czasu. Załóżmy, że każde wywołanie funkcji insert zajmuje stałą ilość czasu. Ze względu na to, że mamy n, minus, 1 wywołań funkcji insert, jeśli każde wywołanie zajmuje stałą ilość czasu c, wtedy całkowity czas sortowania przez wstawianie wynosi c, dot, left parenthesis, n, minus, 1, right parenthesis, co z kolei wynosi \Theta, left parenthesis, n, right parenthesis, a nie \Theta, left parenthesis, n, squared, right parenthesis.
Czy może się zdarzyć, że żadna z powyższych sytuacji nie będzie miała miejsca? Czy każde wywołanie funkcji insert może powodować, że każdy element w podtablicy będzie musiał być przesunięty o jedną pozycję w prawo? Czy każde wywołanie funkcji insert może nie wymagać przesuwania elementów? Odpowiedź brzmi: tak. Wywołanie funkcji insert powoduje, że każdy element jest przesuwany, jeśli wstawiany klucz jest mniejszy niż każdy element po jego lewej stronie. Zatem jeśli każdy element jest większy lub równy swoim sąsiadom po lewej stronie, czas sortowania przez wstawianie wynosi \Theta, left parenthesis, n, right parenthesis. Co to oznacza, że każdy element jest mniejszy od swojego sąsiada po lewej stronie? To znaczy, że tablica jest posortowana w odwrotnej kolejności np. [11, 7, 5, 3, 2]. Zatem przypadek odwrotnie posortowanej tablicy jest najgorszym przypadkiem dla sortowania przez wstawianie.
Co z przeciwnym przypadkiem? Wywołanie funkcji insert powoduje, że nie ma elementów do przesuwania jeśli klucz, który chcemy wstawić jest większy lub równy każdemu elementowi po swojej lewej stronie. Zatem jeśli każdy element jest większy lub równy swoim sąsiadom po lewej stronie, czas sortowania przez wstawianie wynosi \Theta, left parenthesis, n, right parenthesis. Taka sytuacja ma miejsce, gdy tablica, do której wstawiamy element, jest już posortowana, zatem tablica posortowana to najlepszy przypadek dla sortowania przez wstawianie.
Co jeszcze możemy powiedzieć o czasie wykonywania sortowania przez wstawianie? Załóżmy, że elementy tablicy ułożone są w losowym porządku. W takim przypadku, uśredniając, oczekujemy, że każdy element jest mniejszy niż połowa elementów z jego lewej strony. Wówczas wywołanie funkcji insert na k-elementowej podtablicy spowoduje przesunięcie średnio k, slash, 2 elementów. Czas wykonania wynosi wtedy połowę czasu potrzebnego dla najgorszego przypadku. Jednak w notacji asymptotycznej, gdzie stałe współczynniki nie mają znaczenia, czasu wykonania sortowania w średnim przypadku wciąż wynosi \Theta, left parenthesis, n, squared, right parenthesis - tak jak w najgorszym przypadku.
A co gdybyśmy wiedzieli, że tablica jest "prawie posortowana"? Każdy element na początku jest w pewnej stałej odległości (np. 17) od pozycji, w której będzie się znajdował po wykonaniu sortowania? Wówczas każde wywołanie funkcji insert powodowałoby przesunięcie co najwyżej 17 elementów a czas wykonania jednej funkcji insert na k-elementowej podtablicy wynosiłby co najwyżej 17, dot, c. Biorąc pod uwagę n, minus, 1 wywołań funkcji insert, czas wykonania wynosi 17, dot, c, dot, left parenthesis, n, minus, 1, right parenthesis, co oznacza \Theta, left parenthesis, n, right parenthesis - tak jak w najlepszym przypadku. Zatem sortowanie przez wstawianie jest szybkie, gdy mamy "prawie posortowaną" tablicę.
Podsumowując, czas wykonania dla sortowania przez wstawianie wynosi:
  • W najgorszym przypadku: \Theta, left parenthesis, n, squared, right parenthesis.
  • W najlepszym przypadku: \Theta, left parenthesis, n, right parenthesis.
  • Średnia w przypadku tablicy losowej \Theta, left parenthesis, n, squared, right parenthesis.
  • W "prawie posortowanym" przypadku: \Theta, left parenthesis, n, right parenthesis.
Jeśli musielibyśmy uogólnić stwierdzenie na wszystkie przypadki sortowania przez wstawianie, powiedzielibyśmy, że wykonuje się ono w czasie O, left parenthesis, n, squared, right parenthesis. Nie można powiedzieć, że przebiega ono w czasie \Theta, left parenthesis, n, squared, right parenthesis dla wszystkich przypadków, skoro najlepszy przypadek przebiega w czasie \Theta, left parenthesis, n, right parenthesis. I jednocześnie nie można powiedzieć, że przebiega ono w czasie \Theta, left parenthesis, n, right parenthesis we wszystkich przypadkach, skoro w najgorszym przypadku czas wykonania wynosi \Theta, left parenthesis, n, squared, right parenthesis.

Materiał powstał we współpracy profesorów z Dartmouth Computer Science Thomasa Cormena i Devina Balkcoma oraz zespołu nauczycieli informatyki Khan Academy. Materiał jest udostępniony na licencji CC-BY-NC-SA.