Sortowanie Dane wejściowe: ciąg n-liczb (kluczy) (a1,a2,a3,...,an−1
Transkrypt
Sortowanie Dane wejściowe: ciąg n-liczb (kluczy) (a1,a2,a3,...,an−1
Sortowanie Dane wejściowe: ciąg n-liczb (kluczy) (a1 , a2 , a3 , . . . , an−1 , an ) Dane wyjściowe: permutacja ciągu wejściowego (a01 , a02 , a03 , . . . , a0n−1 , a0n ) taka, że a01 ¬ a02 ¬ a03 ¬ . . . ¬ a0n−1 ¬ a0n . Będziemy zakładać, że ciąg ten stanowią elementy tablicy A[1...n]. Zadanie 1 Przygotuj algorytm programu - sortowanie przez wstawianie. a) Przeanalizuj algorytm programu - sortowanie przez wstawianie. Schemat blokowy tego algorytmu: Dane wejściowe: tablica A[1...n], którą należy przesortować, Len([A]) oznacza liczbę elementów tablicy. begin i := 2; while i < Len([A]) + 1 do begin key := A[i]; j := i − 1; while j > 0 and key < A[j] do begin A[j + 1] := A[j]; j := j − 1; end A[j + 1] := key; i := i + 1; end end Dane wyjściowe: przesortowana tablica A[n]. b) Niech A oznacza napis SORTOWANIE, Len[A] = 10. Podaj stan tablicy [A] po kolejnych wyjściach z pętli głównej. 1 i key 2 O 3 R 4 5 T O 6 7 8 9 10 W A N I E j A[j] A 1 S SSRTOWANIE OSRTOWANIE 2 S ORRTOWANIE 1 O ORSTOWANIE 3 S ORSTOWANIE 4 T ORSTTWANIE 3 S ORSSTWANIE 2 R ORRSTWANIE 1 O OORSTWANIE 5 T OORSTWANIE AOORSTWNIE ANOORSTWIE AINOORSTWE AINOORSTWE c) Jaka jest złożoność tego algorytmu? Jak często ze sprawdzenia warunku j > 0 wyniknie, że j = 0 ?? Co najwyżej raz. w C# można zmienić kolejność sprawdzania while key < A[j] and j > 0 do Ile razy wykonywana jest operacja porównania? Jaka jest minimalna, a jaka maksymalna liczba przesunięć A[j + 1] ← A[j]? Czy algorytm jest stabilny? Rozwiązanie Złożoność obliczeniowa Pamięciowa – algorytm sortuje w miejscu. Czasowa: Liczba porównań – koszt pesymistyczny W (n) = n(n−1) 2 Liczba porównań – koszt oczekiwany A(n) = n(n+1) 4 Liczba półzamian = Liczba porównań. Zalety Algorytm sortowanie przez wstawianie jest stabilny. d) Zaimplementuj ten algorytm w języku C# dla listy liczbowej. 2 e) Zaimplementuj w C# algorytm sortowania przez wstawianie ze strażnikiem: begin min := 1; for i := 2 to Len([A]) do if A[i] < A[min] then min := i; zamień(A[1], A[min]); for i := 2 to Len([A]) do begin key := A[i]; j := i − 1; while key < A[j] do {A[1] − −strażnik} begin A[j + 1] := A[j]; j := j − 1; end A[j + 1] := key; end end 3 Zadanie 2 Sortowanie przez wstawianie – z wyszukiwaniem binarnym.–wazniak.mimuw.edu.pl W algorytmie sortowania przez wstawianie, jeden z kroków polega na wstawieniu elementu A[i] do uporządkowanego podciągu A[1, . . . , i − 1]. Należy wyszukać największy taki indeks j ¬ i, taki że A[j − 1] ¬ x = A[i]. Miejsce, w które należy wstawić element A[i], można znaleźć za pomocą wyszukiwania binarnego. Przygotuj algorytm takiego programu i przeanalizuj go na przykładzie listy [1, 6, 5, 7, 9, 6]. Rozwiązanie. Możliwe są dwa przypadki: 1. ∀j<i A[j] ¬ x = A[i], czyli klucz x jest na właściwym miejscu 2. x < A[i − 1]. W takim przypadku należy wyszukać binarnie największy taki indeks j < i, taki że A[j − 1] ¬ x = A[i]. W przypadku konieczności zastosowania wyszukiwania binarnego x w liście A[0 : i] możliwe są przypadki: 1. x nie występuje na tej liście, należy znaleźć j < i, A[j − 1] < x < A[j] 2. x występuje co najmniej raz na tej liście, należy znaleźć j < i, A[j − 1] = x ∧ A[j] > x. Oznacza to, że powinien być zwracany prawy skrajny element lewej podlisty, a warunek porównania powinien być postaci if x <= A[k] then return k. l := 0; p := len(A) − 1; while (l < p) do begin k := (l + p) div 2; if x > A[k] then l := k + 1; else p := k; end; if x = A[p] then p = p + 1 return p; W tym algorytmie liczbę wykonywanych porównań można wyznaczyć następująco: w iteracji o numerze i zewnętrznej pętli for wykonuje się co najwyżej dlog ie porównań pomiędzy elementami sortowanego ciągu czyli złożoność obliczeniowa jest równa n X dlog ie = ndlog ne − 2dlog ne + 1. W algorytmie tym, i=2 4 liczba porównań została zmniejszona do liniowo-logarytmicznej, ale liczba przestawień elementów w tablicy, koniecznych do zrobienia tych miejsc, w dalszym ciągu jest w pesymistycznym przypadku kwadratowa. Ta obserwacja pokazuje, że do analizy złożoności algorytmu, dobór operacji dominujących jest kluczowy dla jakości tej analizy. Zadanie 3 X n Pokaż, że dlg ie = ndlg ne − 2dlg ne + 1. i=2 Rozwiązanie. Rozważmy sumę n X dlg ie. i=2 Niech p = blg nc, p + 1 = dlg ne, czyli 2p < n ¬ 2p=1 . Widać, że k+1 2X dlg ie = 2k dlog(2k + i)e = 2k (k + 1). i=2k +1 czyli n X dlg ie = i=2 k+1 p−1 X 2X dlg ie + (n − 2 )dlg ne = k=0 i=2k +1 p−1 X Ile wynosi suma p p−1 X 2k (k + 1) + (n − 2p )dlg ne. k=0 2k (k + 1) ? k=0 Sprawdźmy to dla p = 4 : 1 · 20 + 2 · 21 + 20 + 21 + 21 + (24 − 1) + 3 · 24 + 3 · 24 + 3 · 24 + Twierdzenie p−1 X 3 · 22 22 22 22 + 4 · 23 + 23 + 23 + 23 23 3 2 2 2 · (2 − 1) + 2 · (2 − 1) + 23 23 − (1 + 2 + 22 ) 23 − (23 − 1) 1 = = = = = = = = 2k (k + 1) = (p − 1)2p + 1. k=0 Dowód przez indukcję. n X dlg ie = (blg nc − 1)2blg nc + 1 + (n − 2blg nc )dlg ne) = (dlg ne − 2)2blg nc + i=2 1 + (n − 2blg nc )dlg ne) = ndlg ne − 2dlg ne + 1. 5