Algorytmy i Struktury Danych.

Podobne dokumenty
Algorytmy i Struktury Danych.

Algorytmy i Struktury Danych.

Algorytmy i Struktury Danych.

Podstawowe algorytmy i ich implementacje w C. Wykład 9

Strategia "dziel i zwyciężaj"

Sortowanie przez scalanie

Analiza algorytmów zadania podstawowe

Algorytmy i Struktury Danych.

Programowanie Proceduralne

Wykład 5. Sortowanie w czasie liniowologarytmicznym

Definicja. Ciąg wejściowy: Funkcja uporządkowująca: Sortowanie polega na: a 1, a 2,, a n-1, a n. f(a 1 ) f(a 2 ) f(a n )

Programowanie w VB Proste algorytmy sortowania

Algorytmy i struktury danych Sortowanie IS/IO, WIMiIP

Rekurencja. Dla rozwiązania danego problemu, algorytm wywołuje sam siebie przy rozwiązywaniu podobnych podproblemów. Przykład: silnia: n! = n(n-1)!

Informatyka A. Algorytmy

Algorytm selekcji Hoare a. Łukasz Miemus

Algorytmy i Struktury Danych

Algorytmy i Struktury Danych.

Algorytmy sortujące i wyszukujące

Sortowanie w czasie liniowym

Podstawy algorytmiki i programowania - wykład 6 Sortowanie- algorytmy

Struktury Danych i Złożoność Obliczeniowa

Zadanie 1 Przygotuj algorytm programu - sortowanie przez wstawianie.

WYKŁAD 9. Algorytmy sortowania elementów zbioru (tablic) Programy: c4_1.c... c4_3.c. Tomasz Zieliński

Sortowanie danych. Jolanta Bachan. Podstawy programowania

Algorytmy i Struktury Danych.

Analiza algorytmów zadania podstawowe

Struktury danych i złożoność obliczeniowa Wykład 2. Prof. dr hab. inż. Jan Magott

Programowanie proceduralne INP001210WL rok akademicki 2017/18 semestr letni. Wykład 3. Karol Tarnowski A-1 p.

Laboratoria nr 1. Sortowanie

Problemy porządkowe zadania

Algorytmy i Struktury Danych. (c) Marcin Sydow. Introduction. QuickSort. Sortowanie 2. Limit. CountSort. RadixSort. Summary

Uwaga: Funkcja zamień(a[j],a[j+s]) zamienia miejscami wartości A[j] oraz A[j+s].

Efektywna metoda sortowania sortowanie przez scalanie

Sortowanie. LABORKA Piotr Ciskowski

Algorytmy i Struktury Danych. (c) Marcin Sydow. Sortowanie Selection Sort Insertion Sort Merge Sort. Sortowanie 1. Listy dowiązaniowe.

Sortowanie bąbelkowe

Wstęp do programowania. Dziel i rządź. Piotr Chrząstowski-Wachtel

Wstęp do programowania

INFORMATYKA SORTOWANIE DANYCH.

Wykład 3. Metoda dziel i zwyciężaj

Złożoność obliczeniowa algorytmu ilość zasobów komputera jakiej potrzebuje dany algorytm. Pojęcie to

Sortowanie. Bartman Jacek Algorytmy i struktury

Podstawy Informatyki

Sortowanie - wybrane algorytmy

Algorytmy i struktury danych. Co dziś? Tytułem przypomnienia metoda dziel i zwyciężaj. Wykład VIII Elementarne techniki algorytmiczne

Wstęp do programowania INP001213Wcl rok akademicki 2017/18 semestr zimowy. Wykład 9. Karol Tarnowski A-1 p.

Wykład 4. Sortowanie

Algorytmy sortujące 1

Wstęp do programowania

Zaawansowane algorytmy i struktury danych

Algorytmy i złożoność obliczeniowa. Wojciech Horzelski

Jeśli czas działania algorytmu zależy nie tylko od rozmiaru danych wejściowych i przyjmuje różne wartości dla różnych danych o tym samym rozmiarze,

[12] Metody projektowania algorytmów (dziel i rządź, programowanie dynamiczne i algorytmy zachłanne).

Zaawansowane algorytmy i struktury danych

Algorytmy i struktury danych

Laboratoria nr 1. Sortowanie

Matematyczne Podstawy Informatyki

Podstawy Informatyki. Sprawność algorytmów

Laboratorium nr 7 Sortowanie

Jeszcze o algorytmach

PODSTAWY INFORMATYKI wykład 5.

Źródła. N.Wirth Algorithms and Data Structures, 1985 D.E.Knuth The Art of Computer Programming. Vol. 3, 1973

Wykład 2. Poprawność algorytmów

prowadzący dr ADRIAN HORZYK /~horzyk tel.: Konsultacje paw. D-13/325

Sortowanie zewnętrzne

Algorytmy i Struktury Danych, 2. ćwiczenia

Algorytmy i struktury danych

ALGORYTMY I STRUKTURY DANYCH

Porównanie Heap Sort, Counting Sort, Shell Sort, Bubble Sort. Porównanie sortowao: HS, CS, Shs, BS

Zadanie projektowe 1: Struktury danych i złożoność obliczeniowa

Indukcja. Materiały pomocnicze do wykładu. wykładowca: dr Magdalena Kacprzak

Porównanie czasów działania algorytmów sortowania przez wstawianie i scalanie

Uniwersytet Zielonogórski Instytut Sterowania i Systemów Informatycznych. Algorytmy i struktury danych Laboratorium Nr 4

PoniŜej znajdują się pytania z egzaminów zawodowych teoretycznych. Jest to materiał poglądowy.

Wstęp do Informatyki

Algorytmy komputerowe. dr inŝ. Jarosław Forenc

2:8,7 3:9,4 / \ / \ / \ / \ 4:7,3 5:8 6:9,2 7:4

Luty 2001 Algorytmy (4) 2000/2001

Wykład 1_2 Algorytmy sortowania tablic Sortowanie bąbelkowe

Algorytmy i struktury danych. Wykład 6 Tablice rozproszone cz. 2

Rekurencje. Jeśli algorytm zawiera wywołanie samego siebie, jego czas działania moŝe być określony rekurencją. Przykład: sortowanie przez scalanie:

Sortowanie przez wstawianie Insertion Sort

5. Podstawowe algorytmy i ich cechy.

Zasady analizy algorytmów

Teoretyczne podstawy informatyki

Sortowanie. Kolejki priorytetowe i algorytm Heapsort Dynamiczny problem sortowania:

KOPCE KOLEJKI PRIORYTETOWE - PRZYPOMNIENIE KOPCE WYSOKOŚĆ KOPCA KOPCE I KOLEJKI PRIORYTETOWE PROJEKTOWANIE ALGORYTMÓW I METODY SZTUCZNEJ INTELIGENCJI

Algorytm. a programowanie -

Metodyki i Techniki Programowania 2

ZASADY PROGRAMOWANIA KOMPUTERÓW ZAP zima 2014/2015. Drzewa BST c.d., równoważenie drzew, kopce.

Kodowanie informacji

Matematyka dyskretna - wykład - część Podstawowe algorytmy kombinatoryczne

Rekurencja. Przykład. Rozważmy ciąg

Podstawy programowania. Przykłady algorytmów Cz. 2 Sortowanie

Wstęp do Informatyki zadania ze złożoności obliczeniowej z rozwiązaniami

Drzewa poszukiwań binarnych

Temat: Dynamiczne przydzielanie i zwalnianie pamięci. Struktura listy operacje wstawiania, wyszukiwania oraz usuwania danych.

Podstawy Programowania 1 Sortowanie tablic jednowymiarowych. Plan. Sortowanie. Sortowanie Rodzaje sortowania. Notatki. Notatki. Notatki.

Wstęp do programowania

Transkrypt:

Algorytmy i Struktury Danych. Problem Sortowania. Metoda Dziel i zwyciężaj - cd. dr hab. Bożena Woźna-Szcześniak bwozna@gmail.com Jan Długosz University, Poland Wykład 5 Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 1 / 79

Dziel i Zwyciężaj - przykłady zastosowań Znajdowanie największego i najmniejszego elementu zbioru. Wyszukiwanie binarne Potęgowanie liczb Sortowanie szybkie Sortowanie przez scalanie Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 2 / 79

Sortowanie szybkie (ang. Quick Sort) Najczęściej stosowany algorytm sortujacy w praktyce. Podstawowa wersja algorytmu została opracowana przez Sir C.A.R. Hoare a w 1960 roku. Wynalazł go, aby przetłumaczyć tekst rosyjski na angielski Algorytm sortowania szybkiego jest typowym algorytmem rekurencyjnym, pracujacym w oparciu o technikę dziel i zwyciężaj. Algorytm zakłada dekompozycję tablicy na mniejsze podtablice, które łatwiej jest posortować. Figure : Charles Antony Richard Hoare (Tony Hoare, ur. 11 stycznia 1934 w Kolombo, Sri Lanka). W 1980 roku, w dowód uznania za wkład w rozwój języków programowania otrzymał nagrodę Turinga. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 3 / 79

Sortowanie szybkie Zalety: Wady: Działa w miejscu (używa tylko niewielkiego stosu pomocniczego) W średnim przypadku sortowanie szybkie wymaga 2 n log(n) porównań. Metoda sortowania jest niestabilna. W najgorszym przypadku sortowanie szybkie wymaga 1 2 n2 porównań. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 4 / 79

Sortowanie szybkie - Idea Podziel tablicę na dwie części względem pewnego ustalonego elementu, tzw. elementu osiowego (ang. pivot), tak aby na lewo od niego znajdowały się elementy mniejsze, a na prawo elementy większe. Rekurencyjnie posortować elementy na lewo i na prawo od elementu osiowego. Połaczyć posortowane podtablice. Wejście Podział Sortuj lewa Sortuj prawa Wynik Q U I C K S O R T E X A M P L E Element osiowy E I C K O E A M P L Q U R S T X Nie większe Nie mniejsze A C E E I K L M O P Q U R S T X E I C K O E A M P L Q R S T U X A C E E I K L M O P Q R S T U X Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 5 / 79

Sortowanie szybkie - idea Sednem sortowania szybkiego jest proces podziału tablicy, dalej nazywanej A. Podział zmienia kolejność elementów w tablicy A o granicach [left, right] tak, że spełnione sa następujace warunki: Element A[i] znajduje się na właściwej pozycji, dla pewnego i. Elementy A[left],..., A[i 1] nie sa większe od A[i]. Elementy A[i + 1],..., A[right] nie sa mniejsze od A[i]. Najczęściej stosowane strategie wyboru elementu osiowego, tj. A[i]: wybranie pierwszego (lub ostatniego) elementu tablicy. wybranie losowego elementu z tablicy. metoda mediany z trzech. Sortowanie całkowite uzysukje się przez dzielenie tablicy wejściowej na części i rekurencyjne stosowanie metody. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 6 / 79

Sortowanie szybkie - algorytm Algorytm: QuickSort (A, left, right) {A=[left],..., A[right]} 1: if right <= left then 2: return 3: end if 4: i = partition(a, left, right); 5: QuickSort(A, left, i-1). 6: QuickSort(A, i+1, right). Wywołanie: QuickSort(A, 0, n-1) Jeżeli tablica A ma jeden albo mniej elementów, to koniec. W przeciwnym razie, przetwórz tablicę przez procedurę partition, która umieści A[i] na właściwym miejścu (dla pewnego i [left, right]) oraz poprzestawia pozostałe elementy tablicy tak, że procedura wywołania rekurencyjnego zakońcy się w sposób przwidłowy. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 7 / 79

Sortowanie szybkie - procedura podziału partition (A, left, right) 1: x = A[left]; {element osiowy} 2: i = left; 3: for all j = left + 1 to right do 4: if A[j] x then 5: i = i + 1; 6: zamien(a[i],a[j]); 7: end if 8: end for 9: zamien (A[left], A[i]); 10: return i 6 10 13 5 8 3 2 11 i j Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 8 / 79

Sortowanie szybkie - procedura podziału partition (A, left, right) 1: x = A[left]; {element osiowy} 2: i = left; 3: for all j = left + 1 to right do 4: if A[j] x then 5: i = i + 1; 6: zamien(a[i],a[j]); 7: end if 8: end for 9: zamien (A[left], A[i]); 10: return i 6 10 13 5 8 3 2 11 i j 6 10 13 5 8 3 2 11 i j Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 8 / 79

Sortowanie szybkie - procedura podziału partition (A, left, right) 1: x = A[left]; {element osiowy} 2: i = left; 3: for all j = left + 1 to right do 4: if A[j] x then 5: i = i + 1; 6: zamien(a[i],a[j]); 7: end if 8: end for 9: zamien (A[left], A[i]); 10: return i 6 10 13 5 8 3 2 11 i j 6 10 13 5 8 3 2 11 i j 6 10 13 5 8 3 2 11 i j Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 8 / 79

Sortowanie szybkie - procedura podziału partition (A, left, right) 1: x = A[left]; {element osiowy} 2: i = left; 3: for all j = left + 1 to right do 4: if A[j] x then 5: i = i + 1; 6: zamien(a[i],a[j]); 7: end if 8: end for 9: zamien (A[left], A[i]); 10: return i 6 10 13 5 8 3 2 11 i j 6 10 13 5 8 3 2 11 i j 6 10 13 5 8 3 2 11 i j 6 5 13 10 8 3 2 11 i j Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 8 / 79

Sortowanie szybkie - procedura podziału partition (A, left, right) 1: x = A[left]; {element osiowy} 2: i = left; 3: for all j = left + 1 to right do 4: if A[j] x then 5: i = i + 1; 6: zamien(a[i],a[j]); 7: end if 8: end for 9: zamien (A[left], A[i]); 10: return i 6 10 13 5 8 3 2 11 i j 6 10 13 5 8 3 2 11 i j 6 10 13 5 8 3 2 11 i j 6 5 13 10 8 3 2 11 i j 6 5 13 10 8 3 2 11 i j Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 8 / 79

Sortowanie szybkie - procedura podziału partition (A, left, right) 1: x = A[left]; {element osiowy} 2: i = left; 3: for all j = left + 1 to right do 4: if A[j] x then 5: i = i + 1; 6: zamien(a[i],a[j]); 7: end if 8: end for 9: zamien (A[left], A[i]); 10: return i 6 5 13 10 8 3 2 11 i j Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 9 / 79

Sortowanie szybkie - procedura podziału partition (A, left, right) 1: x = A[left]; {element osiowy} 2: i = left; 3: for all j = left + 1 to right do 4: if A[j] x then 5: i = i + 1; 6: zamien(a[i],a[j]); 7: end if 8: end for 9: zamien (A[left], A[i]); 10: return i 6 5 13 10 8 3 2 11 i j 6 5 3 10 8 13 2 11 i j Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 9 / 79

Sortowanie szybkie - procedura podziału partition (A, left, right) 1: x = A[left]; {element osiowy} 2: i = left; 3: for all j = left + 1 to right do 4: if A[j] x then 5: i = i + 1; 6: zamien(a[i],a[j]); 7: end if 8: end for 9: zamien (A[left], A[i]); 10: return i 6 5 13 10 8 3 2 11 i j 6 5 3 10 8 13 2 11 i j 6 5 3 10 8 13 2 11 i j Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 9 / 79

Sortowanie szybkie - procedura podziału partition (A, left, right) 1: x = A[left]; {element osiowy} 2: i = left; 3: for all j = left + 1 to right do 4: if A[j] x then 5: i = i + 1; 6: zamien(a[i],a[j]); 7: end if 8: end for 9: zamien (A[left], A[i]); 10: return i 6 5 13 10 8 3 2 11 i j 6 5 3 10 8 13 2 11 i j 6 5 3 10 8 13 2 11 i j 6 5 3 2 8 13 10 11 i j Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 9 / 79

Sortowanie szybkie - procedura podziału partition (A, left, right) 1: x = A[left]; {element osiowy} 2: i = left; 3: for all j = left + 1 to right do 4: if A[j] x then 5: i = i + 1; 6: zamien(a[i],a[j]); 7: end if 8: end for 9: zamien (A[left], A[i]); 10: return i 6 5 13 10 8 3 2 11 i j 6 5 3 10 8 13 2 11 i j 6 5 3 10 8 13 2 11 i j 6 5 3 2 8 13 10 11 i j 6 5 3 2 8 13 10 11 i j Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 9 / 79

Sortowanie szybkie - procedura podziału partition (A, left, right) 1: x = A[left]; {element osiowy} 2: i = left; 3: for all j = left + 1 to right do 4: if A[j] x then 5: i = i + 1; 6: zamien(a[i],a[j]); 7: end if 8: end for 9: zamien (A[left], A[i]); 10: return i 6 5 3 2 8 13 10 11 i j Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 10 / 79

Sortowanie szybkie - procedura podziału partition (A, left, right) 1: x = A[left]; {element osiowy} 2: i = left; 3: for all j = left + 1 to right do 4: if A[j] x then 5: i = i + 1; 6: zamien(a[i],a[j]); 7: end if 8: end for 9: zamien (A[left], A[i]); 10: return i 6 5 3 2 8 13 10 11 i j 2 5 3 6 8 13 10 11 i Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 10 / 79

Ślad QuickSort z partition left j right 0 1 2 3 4 5 6 7 Wejście 6 10 13 5 8 3 2 11 0 3 7 2 5 3 6 8 13 10 11 0 0 2 2 5 3 6 8 13 10 11 1 2 2 2 3 5 6 8 13 10 11 podziału brak 1 1 2 3 5 6 8 13 10 11 4 4 7 2 3 5 6 8 13 10 11 5 7 7 2 3 5 6 8 11 10 13 5 6 6 2 3 5 6 8 10 11 13 podziału brak 5 5 2 3 5 6 8 10 11 13 Wyjście 2 3 5 6 8 10 11 13 Kolor czerowny oznacza element osiowy. Kolor niebieski oznacza element na właściwej pozycji. Kolor szary oznacza element nieprzetwarzany. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 11 / 79

Sortowanie szybkie - procedura podziału 2 wg. R. Sedgewick int partition2(int a [], int left, int right) { int i = left, j = right+1; while (true) { while (a[++i] < a[left]) if (i == right) break; while (a[left] < a[--j]) if (j == left) break; if (i >= j) break; swap(a, i, j); } swap(a, left, j); return j; } Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 12 / 79

Ślad QuickSort z partition2 left j right 0 1 2 3 4 5 6 7 Wejście 6 10 13 5 8 3 2 11 0 3 7 5 2 3 6 8 13 10 11 0 2 2 3 2 5 6 8 13 10 11 0 1 1 2 3 5 6 8 13 10 11 podziału brak 0 0 2 3 5 6 8 13 10 11 4 4 7 2 3 5 6 8 13 10 11 5 7 7 2 3 5 6 8 11 10 13 5 6 6 2 3 5 6 8 10 11 13 podziału brak 5 5 2 3 5 6 8 10 11 13 Wyjście 2 3 5 6 8 10 11 13 Kolor czerowny oznacza element osiowy. Kolor niebieski oznacza element na właściwej pozycji. Kolor szary oznacza element nieprzetwarzany. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 13 / 79

Ślad QuickSort z partition2 left j right 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Wejście Q U I C K S O R T E X A M P L E 0 10 15 A E I C K L O P M E Q X T R S U 0 0 9 A E I C K L O P M E Q X T R S U 1 3 9 A C E E K L O P M I Q X T R S U 1 1 2 A C E E K L O P M I Q X T R S U podziału brak 2 2 A C E E K L O P M I Q X T R S U 4 5 9 A C E E I K O P M L Q X T R S U podziału brak 4 4 A C E E I K O P M L Q X T R S U 6 8 9 A C E E I K M L O P Q X T R S U 6 7 7 A C E E I K L M O P Q X T R S U podziału brak 6 6 A C E E I K L M O P Q X T R S U podziału brak 9 9 A C E E I K L M O P Q X T R S U 11 15 15 A C E E I K L M O P Q U T R S X 11 14 14 A C E E I K L M O P Q S T R U X 11 12 13 A C E E I K L M O P Q R S T U X podziału brak 11 11 A C E E I K L M O P Q R S T U X podziału brak 13 13 A C E E I K L M O P Q R S T U X Wyjście A C E E I K L M O P Q R S T U X Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 14 / 79

Sortowanie szybkie - złożoność Twerdzenie Algorytm sortowania szybkiego w najgorszym przypadku wymaga 1 2 n2 porównań. Uzasadnienie: Zauważmy, że najgorszym przpadkiem dla algorytmu sortowania szybkiego jest ciag danych już uporzadkowanych w kolejności odwrotnej do pożadanej. Wówczas, liczba porównań wynosi: n + (n 1) + (n 2) +... + 2 + 1 = (n + 1) n 2 Dlaczego: Jeśli procedura podziału partition jako element osiowy wybiera zawsze pierwszy element, to w wyniku podziału, jedna część będzie pusta, a druga będzie zawierała o jeden element mniej niż w poprzednim kroku. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 15 / 79

Sortowanie szybkie - złożoność Założenie: Każdy podział jest perfekcyjnie zbalansowany, czyli daje w wyniku dokładnie równe podzbiory danych. Twierdzenie Algorytm sortowania szybkiego w najlepszym przypadku wymaga n log 2 (n) porównań. Uzasadnienie: Zauważmy, że ponieważ z założenia każdy podział jest perfekcyjnie zbalasowany, to liczba porównań przprowadzanych przez algorytm sortowani szybkiego spełnia następujac a zależność rekurencyjna dla metod typu "dziel i zwyciężaj": T (n) = 2 T (n/2) + Θ(n) 2 T (n/2) - koszt sortowania dwóch podzbiorów. Θ(n) - koszt sprawdzenia każdego elementu wzgledem elementu osiowego. Rozwiazanie zależności w przybliżeniu: T (n) n log 2 (n). Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 16 / 79

Sortowanie szybkie - Złożoność pamięciowa Twierdzenie W przypadku danych losowych algorytm sortowania szybkiego wymaga maksymalnie do obsłużenia rekurencji stosu o rozmiarze proporcjonalnym do log 2 (n). W najgorszym przypadku algorytm sortowania szybkiego wymaga do obsłużenia rekurencji stosu o rozmiarze proporcjonalnym do n. Obserwacja: Jeśli podczas sortowania szybkiego n danych mniejszy z dwóch podzbiorów jest zawsze sortowany jako pierwszy, to rozmiar stosu nigdy nie przekroczy wartości log 2 (n). Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 17 / 79

Nierekurencyjna implementacja sortowania szybkiego #include <stack> void sort(t a[], int l, int r) { stack<t> stos; stos.push(r); stos.push(l); while (!stos.empty()) { l = stos.top(); stos.pop(); r = stos.top(); stos.pop(); if (r <= l) continue; int i = partition(a, l, r); if (i-1 > r-i) { stos.push(i-1); stos.push(l); stos.push(r); stos.push(i+1); } else { stos.push(r); stos.push(i+1); stos.push(i-1); stos.push(l); } } } Wykorzystujemy jawny stos. Wywołanie rekurencyjne zastapione operacjami umieszczania i zdejmowania ze stosu w pętli. Większy z podzbiorów kładziemy na stosie jako pierwszy. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 18 / 79

Sortowanie szybkie - Małe podzbiory Znaczna poprawę algorytmu sortowania szybkiego można uzyskać, jeśli zablokujemy rekurencję dla małych podzbiorów, a w jej miejsce użyjemy np. sortowania przez wstawianie. Algorytm: QuickSort (A, left, right) 1: if right <= left then 2: return ; 3: end if 4: i = partition(a, left, right); 5: QuickSort(A, left, i-1); 6: QuickSort(A, i+1, right); Algorytm: QuickSort (A, left, right,m) 1: if right left <= m then 2: insertsort(a, left, right); 3: return ; 4: end if 5: i = partition(a, left, right); 6: QuickSort(A, left, i-1,m); 7: QuickSort(A, i+1, right,m); Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 19 / 79

Sortowanie szybkie - Małe podzbiory Jeszcze lepsza poprawę algorytmu sortowania szybkiego można uzyskać, jeśli zablokujemy rekurencję dla małych podzbiorów i zakończymy sortowanie, a nastepnie do częściowo uporzadkowanego zbioru zastosujemy metodę sortowania przez wstawianie. Algorytm: QuickSort (A, left, right) 1: if right <= left then 2: return ; 3: end if 4: i = partition(a, left, right); 5: QuickSort(A, left, i-1); 6: QuickSort(A, i+1, right); Algorytm: (A) QuickSort (A, left, right,m) 1: if right left <= m then 2: return ; 3: end if 4: i = partition(a, left, right); 5: QuickSort(A, left, i-1,m); 6: QuickSort(A, i+1, right,m); (B) insertsort(a, left, right); Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 20 / 79

Sortowanie szybkie - podział według mediany z trzech Kolejna poprawka algorytmu sortowania szybkiego polega na zastosowaniu elementu rozgraniczajacego, który z dużym prawdopodobieństwem podzieli zbiór danych w okolicach jego środka. Znana metoda wyznaczania takiego elementu jest metoda mediany z trzech: wybieramy pierwszy, środkowy i ostatni element z tablicy. Zamieniamy element środkowy a[left + right/2] z wartościa a[right 1]. Sortujemy te trzy elementy. Uruchamiamy algorytm podziału dla danych a[left + 1],..., a[right 1] Jeśli połaczymy metodę mediany z metoda odcinania małych zbiorów, możemy uzyskać znaczna poprawę działania sortowania szybkiego. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 21 / 79

Sortowanie szybkie - podział według mediany z trzech Algorytm: (A) QuickSort (A, left, right,m) Odcięcie małych podzbiorów if right left <= m then return ; end if Sortowanie trzech elementów: swap(a[left + right/2], a[r 1]); if a[left] > a[right 1] then swap(a[left], a[right 1]) end if if a[left] > a[right] then swap(a[left], a[right]) end if if a[right 1] > a[right] then swap(a[right 1], a[right]) end if i = partition(a, left+1, right 1); QuickSort(A, left, i-1,m); QuickSort(A, i+1, right,m); (B) insertsort(a, left, right); Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 22 / 79

Sortowanie szybkie- zdublowane klucze Dane zawierajace duża liczbę zdublowanych kluczy sa częstym przypadkiem występujacym w rzeczywistych zastosowaniach: Sortowanie danych osobowych względem roku urodzenia. Sortowanie danych osobowych względem płci Usuwanie duplikatów z listy dyskusyjnej (emailowej) Sorowanie kandydatów do pracy względem ukończonego kierunku Typowe cechy danych ze zdublowanymi kluczami w zastosowaniach: Olbrzymia ilość danych Mała liczba różnych kluczy Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 23 / 79

Przyklad danych ze zdublowanymi kluczami - uprzadkowanie wg. kierunku I Nr-Lotu Kierunek Linia Terminal Rozkład Status DL 9523 Amsterdam(AMS) Delta C 12:25 GA 9213 Amsterdam(AMS) Garuda C 12:25 KL 1364 Amsterdam(AMS) KLM C 12:25 A3 861 Ateny(ATH) Aegean C 10:55 wystartował LO 5603 Ateny(ATH) LOT C 10:55 wystartował BT 5189 Belgrad(BEG) Air-Baltic D-E 11:50 JU 8181 Belgrad(BEG) Air-Serbia D-E 11:50 LO 571 Belgrad(BEG) LOT D-E 11:50 AB 8213 Berlin(TXL) Air-Berlin B 10:40 wystartował LO 535 Budapeszt(BUD) LOT D-E 10:50 wystartował LO 641 Bukareszt(OTP) LOT D-E 11:20 wystartował EI 363 Dublin(DUB) Aer-Lingus B 10:55 wystartował SU 4517 Gdańsk(GDN) Aeroflot D-E 10:45 wystartował OS 8515 Gdańsk(GDN) Austrian D-E 10:45 wystartował LO 3835 Gdańsk(GDN) LOT D-E 10:45 wystartował LO 751 Kijów(KBP) LOT D-E 11:25 wystartował 9U 9513 Kiszyniów(KIV) Air-Moldova D-E 11:15 gate closed LO 513 Kiszyniów(KIV) LOT D-E 11:15 gate closed Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 24 / 79

Przyklad danych ze zdublowanymi kluczami - uprzadkowanie wg. kierunku II SU 3642 Kraków(KRK) Aeroflot D-E 10:40 wystartował LO 3907 Kraków(KRK) LOT D-E 10:40 wystartował LO 765 Lwów(LWO) LOT D-E 12:50 LO 433 Madryt(MAD) LOT D-E 10:40 wystartował SU 2001 Moskwa(SVO) Aeroflot D 12:40 SU 3505 Moskwa(SVO) Aeroflot D-E 10:45 gate closed LO 5677 Moskwa(SVO) LOT D 12:40 LO 675 Moskwa(SVO) LOT D-E 10:45 gate closed LO 341 Nicea(NCE) LOT D-E 10:50 wystartował LO 767 Odessa(ODS) LOT D-E 11:25 wystartował UU 8147 Paryż(CDG) Air-Austral C-E 12:45 AF 1147 Paryż(CDG) Air-France C-E 12:45 DL 8585 Paryż(CDG) Delta C-E 12:45 LO 527 Praga(PRG) LOT D-E 10:50 odwołany BT 5192 Ryga(RIX) Air-Baltic D-E 11:00 wystartował LO 783 Ryga(RIX) LOT D-E 11:00 wystartował W6 1441 Rzym(FCO) Wizz-Air A 12:20 boarding BT 5196 Sofia(SOF) Air-Baltic D-E 11:05 wystartował LO 631 Sofia(SOF) LOT D-E 11:05 wystartował LO 785 Tallinn(TLL) LOT D-E 11:25 odwołany Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 25 / 79

Przyklad danych ze zdublowanymi kluczami - uprzadkowanie wg. kierunku III LO 771 Wilno(VNO) LOT D-E 10:50 wystartował SU 4520 Wrocław(WRO) Aeroflot D-E 10:35 wystartował OS 8531 Wrocław(WRO) Austrian D-E 10:35 wystartował LO 3853 Wrocław(WRO) LOT D-E 10:35 wystartował Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 26 / 79

Sortowanie szybkie - podział na 3 cześci Cel. Podziel tablice na 3 części, tak że: Dane pomiędzy lt i gt sa równe elementowi osiowemu v Elementy nie wieksze od v znajduja się po lewej stronie. Elementy nie mniejsze od v znajduja się po prawej stronie. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 27 / 79

Sortowanie szybkie - podział na 3 cześci wg Dijkstry I Niech v = a[left] będzie elementem osiowym oraz lt = left, gt = right: Sprawdzaj i od lewej do prawej dopóki i <= gt: (a[i] < v): zamień miejscami a[lt] z a[i]; zwiększ o 1 lt oraz i. (a[i] > v): zamień miejscami a[gt] z a[i]; zmniejsz o 1 gt. (a[i] == v): zwiększ o 1 i. lt, i gt P A B X W P P V P D P C Y Z left right v = a[left] = P a[left] = a[0] == v, czyli i = 1 Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 28 / 79

Sortowanie szybkie - podział na 3 cześci wg Dijkstry II v = P, a[left] = a[0] == v, czyli i = 1 lt i gt P A B X W P P V P D P C Y Z left right v = P, a[i] = a[1] = A < v, czyli swap(a[lt], a[i]); zwiększ o 1 lt oraz i lt i gt A P B X W P P V P D P C Y Z left right Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 29 / 79

Sortowanie szybkie - podział na 3 cześci wg Dijkstry III v = P, a[i] = a[2] = B < v, czyli swap(a[lt], a[i]); zwiększ o 1 lt oraz i lt i gt A B P X W P P V P D P C Y Z left right v = P, a[i] = a[3] = X > v, czyli swap(a[gt], a[i]); zmniejsz o 1 gt lt i gt A B P Z W P P V P D P C Y X left right Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 30 / 79

Sortowanie szybkie - podział na 3 cześci wg Dijkstry IV v = P, a[i] = a[3] = Z > v, czyli swap(a[gt], a[i]); zmniejsz o 1 gt lt i gt A B P Y W P P V P D P C Z X left right v = P, a[i] = a[3] = Y > v, czyli swap(a[gt], a[i]); zmniejsz o 1 gt lt i gt A B P C W P P V P D P Y Z X left right Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 31 / 79

Sortowanie szybkie - podział na 3 cześci wg Dijkstry V v = P, a[i] = a[3] = C < v, czyli swap(a[lt], a[i]); zwiększ o 1 lt oraz i lt i gt A B C P W P P V P D P Y Z X left right v = P, a[i] = a[4] = W > v, czyli swap(a[gt], a[i]); zmniejsz o 1 gt lt i gt A B C P P P P V P D W Y Z X left right Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 32 / 79

Sortowanie szybkie - podział na 3 cześci wg Dijkstry VI v = P, a[i] = a[4] = P == v, czyli zwiększ i lt i gt A B C P P P P V P D W Y Z X left right v = P, a[i] = a[5] = P == v, czyli zwiększ i lt i gt A B C P P P P V P D W Y Z X left right Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 33 / 79

Sortowanie szybkie - podział na 3 cześci wg Dijkstry VII v = P, a[i] = a[6] = P == v, czyli zwiększ i lt i gt A B C P P P P V P D W Y Z X left right v = P, a[i] = a[7] = V > v, czyli swap(a[gt], a[i]); zmniejsz o 1 gt lt i gt A B C P P P P D P V W Y Z X left right Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 34 / 79

Sortowanie szybkie - podział na 3 cześci wg Dijkstry VIII v = P, a[i] = a[7] = D < v, czyli swap(a[lt], a[i]); zwiększ o 1 lt oraz i lt i, gt, A B C D P P P P P V W Y Z X left right v = P, a[i] = a[8] = P == v, czyli zwiększ i. Uwaga! Po zwiększeniu i > gt! lt gt i A B C D P P P P P V W Y Z X left right Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 35 / 79

Sortowanie szybkie - podział na 3 cześci wg Dijkstry IX Tablica po wykonaniu podzialu na 3 części: lt gt i A B C D P P P P P V W Y Z X left right Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 36 / 79

Sortowanie szybkie - podział na 3 części - kod w C++ void sort(t a[], int left, int right) { if (right <= left) return; T v = a[left]; int lt = left, gt = right, i = left; while (i <= gt) { if (a[i] < v) swap(a, lt++, i++); else if (a[i] > v) swap(a, i, gt--); else i++; } sort(a, left, lt - 1); sort(a, gt + 1, right); } Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 37 / 79

Dziel i Zwyciężaj - przykłady zastosowań Znajdowanie największego i najmniejszego elementu zbioru. Wyszukiwanie binarne Potęgowanie liczb Sortowanie szybkie Sortowanie przez scalanie Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 38 / 79

Sortowanie przez scalanie Sortowanie przez scalanie (ang. merge sort) jest typowym algorytmem rekurencyjnym, pracujacym w oparciu o technikę dziel i zwyciężaj. Autorstwo sortowania przez scalanie przypisuje się Johnowi von Neumannowi 1. Metoda sortowania jest stabilna Najważniejsza własnościa algorytmu jest to, że algorytm ten sortuje tablice n-elementowa w czasie proporcjonalnym do n log 2 (n) bez względu na to, jaki jest zbiór wejściowy. Podstawowa wada sortowania przez scalanie jest to, że proste implementacje wymagaja dodatkowego obszaru pamięci, proporcjonalnego do liczby danych wejściowych n. Sortowanie przez scalanie zalecane jest do sortowania danych sekwencyjnych, np. list. 1 https://pl.wikipedia.org/wiki/john_von_neumann Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 39 / 79

Sortowanie przez scalanie Idea Podziel tablicę na dwie równe połowy. Rekurencyjnie sortuj elementy w każdej połowie. Połacz posortowane podtablice w jedna. Wejście Sortuj lewa Sortuj prawa Połacz Wyniki M E R G E S O R T E X A M P L E E E G M O R R S T E X A M P L E E E G M O R R S A E E L M P T X A E E E E G L M M O P R R S T X Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 40 / 79

Sortowanie przez scalanie - algorytm Algorytm: MergeSort (A, Aux left, right) {A=[left],..., A[right]; Aux=A} 1: if right <= left then 2: return 3: end if 4: mid = left + (right left)/2; 5: MergeSort(A, Aux, left, mid); 6: MergeSort(A, Aux, mid+1, right). 7: merge(a, Aux, left, mid, right); Wywołanie: MergeSort(A, Aux, 0, n-1) Jeżeli tablica A ma jeden albo mniej elementów, to koniec. W przeciwnym razie, oblicz środek tablicy a następnie rekurencyjnie posortuj A[1..mid] i A[mid+1..n]. Scal przy pomocy prcocedury merge obie połowy A w jedna posortowana tablicę przy pomocy tablicy pomocniczej Aux. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 41 / 79

Sortowanie przez scalanie - Operacja scalania Zapamiętujemy pozycje najmniejszego elementu w każdej posortowanej połówce. Wstawiamy najmniejszy z dwóch wskazywanych elementów do tablicy pomocniczej. Operacje powtarzamy dopóty, dopóki nie posortujemy wszystkich elementów. 1 7 11 14 16 Najmniejszy nieprzetworzony: 1 8 9 12 18 20 Najmniejszy nieprzetworzony: 8 Minimum z 1 i 8 1 Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 42 / 79

Sortowanie przez scalanie - Operacja scalania Zapamiętujemy pozycje najmniejszego elementu w każdej posortowanej połówce. Wstawiamy najmniejszy z dwóch wskazywanych elementów do tablicy pomocniczej. Operacje powtarzamy dopóty, dopóki nie posortujemy wszystkich elementów. 1 7 11 14 16 Najmniejszy nieprzetworzony: 7 8 9 12 18 20 Najmniejszy nieprzetworzony: 8 Minimum z 7 i 8 1 7 Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 43 / 79

Sortowanie przez scalanie - Operacja scalania Zapamiętujemy pozycje najmniejszego elementu w każdej posortowanej połówce. Wstawiamy najmniejszy z dwóch wskazywanych elementów do tablicy pomocniczej. Operacje powtarzamy dopóty, dopóki nie posortujemy wszystkich elementów. 1 7 11 14 16 Najmniejszy nieprzetworzony: 11 8 9 12 18 20 Najmniejszy nieprzetworzony: 8 Minimum z 11 i 8 1 7 8 Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 44 / 79

Sortowanie przez scalanie - Operacja scalania Zapamiętujemy pozycje najmniejszego elementu w każdej posortowanej połówce. Wstawiamy najmniejszy z dwóch wskazywanych elementów do tablicy pomocniczej. Operacje powtarzamy dopóty, dopóki nie posortujemy wszystkich elementów. 1 7 11 14 16 Najmniejszy nieprzetworzony: 11 8 9 12 18 20 Najmniejszy nieprzetworzony: 9 Minimum z 11 i 9 1 7 8 9 Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 45 / 79

Sortowanie przez scalanie - Operacja scalania Zapamiętujemy pozycje najmniejszego elementu w każdej posortowanej połówce. Wstawiamy najmniejszy z dwóch wskazywanych elementów do tablicy pomocniczej. Operacje powtarzamy dopóty, dopóki nie posortujemy wszystkich elementów. 1 7 11 14 16 Najmniejszy nieprzetworzony: 11 8 9 12 18 20 Najmniejszy nieprzetworzony: 12 Minimum z 11 i 12 1 7 8 9 11 Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 46 / 79

Sortowanie przez scalanie - Operacja scalania Zapamiętujemy pozycje najmniejszego elementu w każdej posortowanej połówce. Wstawiamy najmniejszy z dwóch wskazywanych elementów do tablicy pomocniczej. Operacje powtarzamy dopóty, dopóki nie posortujemy wszystkich elementów. 1 7 11 14 16 Najmniejszy nieprzetworzony: 14 8 9 12 18 20 Najmniejszy nieprzetworzony: 12 Minimum z 14 i 12 1 7 8 9 11 12 Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 47 / 79

Sortowanie przez scalanie - Operacja scalania Zapamiętujemy pozycje najmniejszego elementu w każdej posortowanej połówce. Wstawiamy najmniejszy z dwóch wskazywanych elementów do tablicy pomocniczej. Operacje powtarzamy dopóty, dopóki nie posortujemy wszystkich elementów. 1 7 11 14 16 Najmniejszy nieprzetworzony: 14 8 9 12 18 20 Najmniejszy nieprzetworzony: 18 Minimum z 14 i 18 1 7 8 9 11 12 14 Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 48 / 79

Sortowanie przez scalanie - Operacja scalania Zapamiętujemy pozycje najmniejszego elementu w każdej posortowanej połówce. Wstawiamy najmniejszy z dwóch wskazywanych elementów do tablicy pomocniczej. Operacje powtarzamy dopóty, dopóki nie posortujemy wszystkich elementów. 1 7 11 14 16 Najmniejszy nieprzetworzony: 16 8 9 12 18 20 Najmniejszy nieprzetworzony: 18 Minimum z 16 i 18 1 7 8 9 11 12 14 16 Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 49 / 79

Sortowanie przez scalanie - Operacja scalania Zapamiętujemy pozycje najmniejszego elementu w każdej posortowanej połówce. Wstawiamy najmniejszy z dwóch wskazywanych elementów do tablicy pomocniczej. Operacje powtarzamy dopóty, dopóki nie posortujemy wszystkich elementów. 1 7 11 14 16 Najmniejszy nieprzetworzony: - 8 9 12 18 20 Nieprzetworzone: 18 i 20 1 7 8 9 11 12 14 16 18 20 Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 50 / 79

Sortowanie przez scalanie - operacja scalania Algorytm: merge (A, Aux, left, mid, right) 1: for k = left to right do 2: Aux[k] = A[k]; k=k+1; 3: end for 4: i = left; j = mid+1; 5: for k = left to right do 6: if i > mid then 7: A[k]= Aux[j]; j=j+1; 8: else if j > right then 9: A[k]= Aux[i]; i=i+1; 10: else if Aux[j]< Aux[i] then 11: A[k]= Aux[j]; j=j+1; 12: else 13: A[k]= Aux[i]; i=i+1; 14: end if 15: k=k+1; 16: end for Kopiowanie tablicy A do Aux: 0 1 2 3 4 5 6 7 A 1 7 11 14 8 9 12 18 Aux1 7 11 14 8 9 12 18 i = left = 0, j = mid + 1 = 4, Aux[j] >= Aux[i], k = 0 A[k] = Aux[i]; i = i + 1; k = k + 1; 0 1 2 3 4 5 6 7 A 1 7 11 14 8 9 12 18 Aux 1 7 11 14 8 9 12 18 i,k j A 1 7 11 14 8 9 12 18 Aux 1 7 11 14 8 9 12 18 i,k j Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 51 / 79

Sortowanie przez scalanie - operacja scalania Algorytm: merge (A, Aux, left, mid, right) 1: for k = left to right do 2: Aux[k] = A[k]; k=k+1; 3: end for 4: i = left; j = mid+1; 5: for k = left to right do 6: if i > mid then 7: A[k]= Aux[j]; j=j+1; 8: else if j > right then 9: A[k]= Aux[i]; i=i+1; 10: else if Aux[j]< Aux[i] then 11: A[k]= Aux[j]; j=j+1; 12: else 13: A[k]= Aux[i]; i=i+1; 14: end if 15: k=k+1; 16: end for i = k = 1, j = 4, Aux[j] >= Aux[i] A[k] = Aux[i]; i+ = 1; k+ = 1; 0 1 2 3 4 5 6 7 A 1 7 11 14 8 9 12 18 Aux 1 7 11 14 8 9 12 18 i,k j A 1 7 11 14 8 9 12 18 Aux 1 7 11 14 8 9 12 18 i,k j i = k = 2, j = 4, Aux[j] < Aux[i] A[k] = Aux[j]; j+ = 1; k+ = 1 0 1 2 3 4 5 6 7 A 1 7 8 14 8 9 12 18 Aux 1 7 11 14 8 9 12 18 i k j Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 52 / 79

Sortowanie przez scalanie - operacja scalania Algorytm: merge (A, Aux, left, mid, right) 1: for k = left to right do 2: Aux[k] = A[k]; k=k+1; 3: end for 4: i = left; j = mid+1; 5: for k = left to right do 6: if i > mid then 7: A[k]= Aux[j]; j=j+1; 8: else if j > right then 9: A[k]= Aux[i]; i=i+1; 10: else if Aux[j]< Aux[i] then 11: A[k]= Aux[j]; j=j+1; 12: else 13: A[k]= Aux[i]; i=i+1; 14: end if 15: k=k+1; 16: end for i = 2, j = 5, k = 3, Aux[j] < Aux[i] A[k] = Aux[j]; j+ = 1; k+ = 1 0 1 2 3 4 5 6 7 A 1 7 8 14 8 9 12 18 Aux 1 7 11 14 8 9 12 18 i k j A 1 7 8 9 8 9 12 18 Aux 1 7 11 14 8 9 12 18 i k j i = 2, j = 6, Aux[j] >= Aux[i], k = 4 A[k + +] = Aux[i + +] 0 1 2 3 4 5 6 7 A 1 7 8 9 11 9 12 18 Aux 1 7 11 14 8 9 12 18 i k j Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 53 / 79

Sortowanie przez scalanie - operacja scalania Algorytm: merge (A, Aux, left, mid, right) 1: for k = left to right do 2: Aux[k] = A[k]; k=k+1; 3: end for 4: i = left; j = mid+1; 5: for k = left to right do 6: if i > mid then 7: A[k]= Aux[j]; j=j+1; 8: else if j > right then 9: A[k]= Aux[i]; i=i+1; 10: else if Aux[j]< Aux[i] then 11: A[k]= Aux[j]; j=j+1; 12: else 13: A[k]= Aux[i]; i=i+1; 14: end if 15: k=k+1; 16: end for i = 3, j = 6, Aux[j] < Aux[i], k = 5 A[k + +] = Aux[j + +] 0 1 2 3 4 5 6 7 A 1 7 8 9 11 9 12 18 Aux 1 7 11 14 8 9 12 18 i k j A 1 7 8 9 11 12 12 18 Aux 1 7 11 14 8 9 12 18 i k j i = 3, j = 7, Aux[j] >= Aux[i], k = 6 A[k + +] = Aux[i + +] 0 1 2 3 4 5 6 7 A 1 7 8 9 11 12 14 18 Aux 1 7 11 14 8 9 12 18 i k,j Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 54 / 79

Sortowanie przez scalanie - operacja scalania Algorytm: merge (A, Aux, left, mid, right) 1: for k = left to right do 2: Aux[k] = A[k]; k=k+1; 3: end for 4: i = left; j = mid+1; 5: for k = left to right do 6: if i > mid then 7: A[k]= Aux[j]; j=j+1; 8: else if j > right then 9: A[k]= Aux[i]; i=i+1; 10: else if Aux[j]< Aux[i] then 11: A[k]= Aux[j]; j=j+1; 12: else 13: A[k]= Aux[i]; i=i+1; 14: end if 15: k=k+1; 16: end for i = 4, j = 7, i > mid, k = 7 A[k + +] = Aux[j + +], k, j > right 0 1 2 3 4 5 6 7 A 1 7 8 9 11 12 14 18 Aux1 7 11 14 8 9 12 18 i j,k A 1 7 8 9 11 12 14 18 Aux1 7 11 14 8 9 12 18 Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 55 / 79

Sortowanie przez scalanie - Koszt algorytmu Twierdzenie Algorytm sortowania przez scalanie zarówno w najlepszym jak i najgorszym przypadku wymaga n log 2 (n) porównań. Twierdzenie Algorytm sortowania przez scalanie wymaga dodatkowego obszaru pamięci proporcjonalnego do liczby danych n. Twierdzenie Algorytm sortowania przez scalanie jest stabilny, jeśli stabilna jest procedura realizujaca operację scalania zbiorów. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 56 / 79

Sortowanie przez scalanie - Koszt algorytmu T (n) MergeSort A[1..n] Θ(1) Jeśli n = 1, to koniec 2 T (n/2) Jeśli n 2, rekurencyjnie posortuj A[1..n/2] i A[n/2+1..n]. Θ(n) Scal obie połowy A w jedna posortowana tablicę. T (n) = Rozwiazanie zależności: { Θ(1) n = 1 2 T (n/2) + Θ(n) n > 1 T (n) = Θ(n log 2 (n)) Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 57 / 79

Sortowanie przez scalanie - Koszt algorytmu Lemat. Niech T (n) oznacza koszt sortowania zbioru n-elementowego. Jeżeli T (n) spełnia zależność T (n) = 2T (n/2) + n dla n > 1 oraz T (1) = 0, to T (n) = n log 2 (n). Dowód indukcyjny (przy założeniu, że n jest potęga 2) Przypadek bazowy: n = 1. Założenie indukcyjne: T (n) = n log 2 (n). Cel: pokazać, że T (2n) = 2n log 2 (2n). T (2n) = 2 T (n) + 2 n Dane = 2 n log 2 (n) + 2 n Założenie indukcyjne = 2 n (log 2 (2 n) 1) + 2 n Obliczenia = 2 n log 2 (2 n) Koniec Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 58 / 79

Sortowanie przez scalanie - Małe podzbiory Znaczna poprawę algorytmu sortowania przez scalanie można uzyskać, jeśli zablokujemy rekurencję dla małych podzbiorów, a w jej miejsce użyjemy np. sortowania przez wstawianie. Algorytm: MergeSort (A, Aux left, right) {A=[left],..., A[right]; Aux=A} 1: if right <= left then 2: return 3: end if 4: mid = left + (right left)/2; 5: MergeSort(A, Aux, left, mid); 6: MergeSort(A, Aux, mid+1, right). 7: merge(a, Aux, left, mid, right); Algorytm: MergeSort (A, Aux left, right,m) 1: if right left <= m then 2: insertsort(a, left, right); 3: return ; 4: end if 5: mid = left + (right left)/2; 6: MergeSort(A, Aux, left, mid); 7: MergeSort(A, Aux, mid+1, right). 8: merge(a, Aux, left, mid, right); Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 59 / 79

Sortowanie przez scalanie - praktyczne ulepszenia Algorytm: MergeSort (A, Aux left, right) {A=[left],..., A[right]; Aux=A} 1: if right <= left then 2: return 3: end if 4: mid = left + (right left)/2; 5: MergeSort(A, Aux, left, mid); 6: MergeSort(A, Aux, mid+1, right). 7: if A[mid] <= A[mid + 1] then 8: return 9: end if 10: merge(a, Aux, left, mid, right); Zatrzymaj sortowanie, jeśli największa wartość w lewej połowie jest mniejsza lub równa najmniejszej wartości z prawej połowy. Lewa połowa Prawa połowa A B C D E F G H I J M N F < G A B C D E F G H I J M N Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 60 / 79

Sortowanie przez scalanie - eliminacja kopiowania do tablicy pomocniczej Algorytm: MergeSort (A, Aux left, right) {A=[left],..., A[right]; Aux=A} 1: if right <= left then 2: return 3: end if 4: mid = left + (right left)/2; 5: MergeSort(Aux, A, left, mid); 6: MergeSort(Aux, A, mid+1, right). 7: merge(a, Aux, left, mid, right); Wywołanie: Utwórz Aux o rozmiarze A i skopiuj A do Aux. MergeSort(Aux, A, 0, n-1) merge (A, Aux, left, mid, right) 1: i = left; j = mid+1; 2: for k = left to right do 3: if i > mid then 4: Aux[k]= A[j]; j=j+1; 5: else if j > right then 6: Aux[k]= A[i]; i=i+1; 7: else if A[j]< A[i] then 8: Aux[k]= A[j]; j=j+1; 9: else 10: Aux[k]= A[i]; i=i+1; 11: end if 12: k=k+1; 13: end for Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 61 / 79

Inne rodzaje sortowań sortowanie przez zliczanie sortowanie pozycyjne Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 62 / 79

Sortowanie przez zliczanie -idea Zadanie: Posortujmy ciag: 3,6,3,2,7,1,7,1. Rozwiazanie: Zliczamy (w jednym korku) liczbę wystapień poszczególnych liczb: Liczba 1 występuje 2 razy Liczba 2 występuje 1 raz Liczba 3 występuje 2 razy Liczba 4 występuje 0 razy Liczba 5 występuje 0 razy Liczba 6 występuje 1 raz Liczba 7 występuje 2 razy Tworzymy posortowany ciag na podstawie danych o liczbie wystapień: 1,1,2,3,3,6,7,7. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 63 / 79

Sortowanie przez zliczanie -idea Uwagi Zadanie: Posortujmy ciag: 3,6,3,2,7,1,7,1. Rozwiazanie: Zliczamy (w jednym korku) liczbę wystapień poszczególnych liczb: Liczba 1 występuje 2 razy Liczba 2 występuje 1 raz Liczba 3 występuje 2 razy Liczba 4 występuje 0 razy Liczba 5 występuje 0 razy Liczba 6 występuje 1 raz Liczba 7 występuje 2 razy Tworzymy posortowany ciag na podstawie danych o liczbie wystapień: 1,1,2,3,3,6,7,7. Proces zliczania odbywa się w jednym kroku. Nie dochodzi do ani jednej zamiany elementów. Proces tworzenia tablicy wynikowej odbywa się w jednym kroku. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 63 / 79

Sortowanie przez zliczanie - algorytm Wejście: A[0..n 1], gdzie A[j] {0, 1, 2,..., k 1}. Wyjście: B[0..n 1], posortowana. Tablica Pomocnicza: C[0..k 1]. {A=[0,...,n-1]} Algorytm: Counting-sort(A,B,k) 1: for all i = 0 to k 1 do 2: C[i] = 0; {Zerowanie tablicy} 3: end for 4: for all i = 0 to n 1 do 5: C[A[i]] = C[A[i]] + 1; 6: end for{//c[i] zawiera teraz liczbe elementów równych i} 7: for all i = 1 to k 1 do 8: C[i] = C[i] + C[i 1]; 9: end for{//c[i] zawiera teraz liczbę elementów mniejszych badź równych i} 10: for all i = n 1 downto 0 do 11: C[A[i]] := C[A[i]] 1; 12: B[C[A[i]]] := A[i]; 13: end for Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 64 / 79

Sortowanie przez zliczanie -przykład Require: Counting-sort(A,B,k) 1: for all i = 0 to k 1 do 2: C[i] = 0; 3: end for 4: for all i = 0 to n 1 do 5: C[A[i]] = C[A[i]] + 1; 6: end for 7: for all i = 1 to k 1 do 8: C[i] = C[i] + C[i 1]; 9: end for 10: for all i = n 1 downto 0 do 11: C[A[i]] := C[A[i]] 1; 12: B[C[A[i]]] := A[i]; 13: end for Wejście: (n = 5, k = 5) A: 4 1 3 4 3 B: C: Linie 1-3 A: 4 1 3 4 3 B: C: 0 0 0 0 0 Linie 4-6 A: 4 1 3 4 3 B: i=0 0 0 0 0 1 i=1 0 1 0 0 1 C: i=2 0 1 0 1 1 i=3 0 1 0 1 2 i=4 0 1 0 2 2 Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 65 / 79

Sortowanie przez zliczanie -przykład Require: Counting-sort(A,B,k) 1: for all i = 0 to k 1 do 2: C[i] = 0; 3: end for 4: for all i = 0 to n 1 do 5: C[A[i]] = C[A[i]] + 1; 6: end for 7: for all i = 1 to k 1 do 8: C[i] = C[i] + C[i 1]; 9: end for 10: for all i = n 1 downto 0 do 11: C[A[i]] := C[A[i]] 1; 12: B[C[A[i]]] := A[i]; 13: end for Linie 7-9 A: 4 1 3 4 3 B: C: 0 1 0 2 2 C: i= 1 0 1 0 2 2 C: i= 2 0 1 1 2 2 C: i= 3 0 1 1 3 2 C: i= 4 0 1 1 3 5 Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 66 / 79

Sortowanie przez zliczanie -przykład Require: Counting-sort(A,B,k) 1: for all i = 0 to k 1 do 2: C[i] = 0; 3: end for 4: for all i = 0 to n 1 do 5: C[A[i]] = C[A[i]] + 1; 6: end for 7: for all i = 1 to k 1 do 8: C[i] = C[i] + C[i 1]; 9: end for 10: for all i = n 1 downto 0 do 11: C[A[i]] := C[A[i]] 1; 12: B[C[A[i]]] := A[i]; 13: end for Linie 10-13 A: 4 1 3 4 3 C: 0 1 1 3 5 C, i = 4: 0 1 1 2 5 B, i = 4: - - 3 - - C, i = 3: 0 1 1 2 4 B, i = 3: - - 3-4 C, i = 2: 0 1 1 1 4 B, i = 2: - 3 3-4 C, i = 1: 0 0 1 1 4 B, i = 1: 1 3 3-4 C, i = 0: 0 0 1 1 3 B, i = 0: 1 3 3 4 4 Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 67 / 79

Sortowanie przez zliczanie - Złożoność obliczeniowa Algorytm: Counting-sort(A,B,k) 1: for all i = 1 to k 1 do 2: C[i] := 0; 3: end for{θ(k)} 4: for all i = 0 to n 1 do 5: C[A[i]] := C[A[i]] + 1; 6: end for{θ(n)} 7: for all i = 1 to k 1 do 8: C[i] := C[i] + C[i 1]; 9: end for{θ(k)} 10: for all i = n 1 downto 0 do 11: B[C[A[i]]] := A[i]; 12: C[A[i]] := C[A[i]] 1; 13: end for{θ(n)} Złożoność obliczeniowa Counting-sort = Θ(n + k) Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 68 / 79

Sortowanie przez zliczanie - Złożoność obliczeniowa Można sortować tylko wartości całkowite. Efektywność sortowania silnie zależy od zakresu k. Jeżeli k jest małe, np. k = O(n), to czas sortowania jest bardzo dobry, tzn. Θ(n). Przykładowo, dla danych kodowalnych na 1 bajcie, k = 2 8 = 256 - pomocnicza tablica ma zatem rozmiar 256. Wówczas counting-sort działa naprawdę szybko, tj. w czasie (256 + n) = Θ(n). Jeżeli k jest duże, to algorym już nie jest taki dobry!!!. Przykładowo, dla danych kodowalnych na 4 bajtach, k = 2 32, czyli okolo 4.2 biliona. Zatem k jest całkiem duże. Wymagana pomocnicza tablica ma rozmiar 4.2 biliona, czyli zajmie około 16 giga-bajtów. Czyli na samym starcie już nie jest dobrze... potrzebny jest super komputer z conajmniej 16 gigabajtami RAM-u. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 69 / 79

Sortowanie przez zliczanie jest stabilne Sortowanie przez zliczanie jest stabilne: zachowuje wejściowy porzadek wśród równych elementów. A: 4 1 3 4 3 B 1 3 3 4 4 Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 70 / 79

Herman Hollerith (1860-1929) Wynalazca kart perforowanych. Ustalił standardowy format karty perforowanej o rozmiarze banknotu jednodolarowego. W 1890 zbudował pierwszy tabulator -sorter kart dziurkowanych - urzadzenie oparte na idei Jacquarda, służace do mechanicznego sporzadzania zestawień danych, ich klasyfikowania, przetwarzania i powielania. Pozwoliło ono przeprowadzić w USA (wtedy 60 milionów ludzi) spis powszechny w dwa i pół roku. Hollerith w 1911 założył firmę Tabulating Machine Company, z której w 1924 wyłoniła się firma IBM (International Business Machines). Źródło:https: //pl.wikipedia. org/wiki/ Herman_ Hollerith Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 71 / 79

Karta dziurkowana Źródło: https://pl.wikipedia.org/wiki/karta_dziurkowana Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 72 / 79

Geneza sortowania pozycyjnego Oto cytat z roku 1889 opisujacy patent (maszynę tabulacyjna) Hollerith a The most complicated combinations can readily be counted with comparatively few counters or relays by first assorting the cards according to the first items entering into the combinations, then reassorting each group according to the second item entering into the combination, and so on, and finally counting on a few counters the last item of the combination for each group of cards. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 73 / 79

Sortowanie pozycyjne Pochodzenie: sorter kart dziurkowanych Herman Hollerith a. Sortowanie cyfra po cyfrze. Niepoprawna idea Hollerith a: sortowanie wzgledem najbardziej znaczacej cyfry. Właściwa idea: sortowanie stabilne przy użyciu pomocniczego algorytmy sortujacego wzgledem najmniej znaczacej cyfry. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 74 / 79

Sortowanie pozycyjne Idea Pochodzenie: sorter kart dziurkowanych Herman Hollerith a. Sortowanie cyfra po cyfrze. Niepoprawna idea Hollerith a: sortowanie wzgledem najbardziej znaczacej cyfry. Właściwa idea: sortowanie stabilne przy użyciu pomocniczego algorytmy sortujacego wzgledem najmniej znaczacej cyfry. Sortowanie pozycyjne (ang. radix sort) porzadkuje stabilnie ciagi wartości (liczb, słów) względem konkretnych cyfr, znaków itp., kolejno od najmniej znaczacych do najbardziej znaczacych pozycji. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 74 / 79

Sortowanie pozycyjne - algorytm Require: Zbiór n-elementowych ciagów A Algorytm: RadixSort 1: for all i = n 1 downto 0 do 2: sortuj stabilnie ciagi według i-tej pozycji; 3: end for Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 75 / 79

Sortowanie pozycyjne - algorytm Require: Zbiór n-elementowych ciagów A Algorytm: RadixSort 1: for all i = n 1 downto 0 do 2: sortuj stabilnie ciagi według i-tej pozycji; 3: end for Przykład Wejście: 523 456 673 666 567 I przebieg: 523 673 456 666 567 II przebieg: 523 456 666 567 673 III przebieg: 456 523 567 666 673 Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 75 / 79

Sortowanie pozycyjne - analiza Złożoność algorymu zależy od wybranego pomocniczego stabilnego algorytmu sortujacego, np:. Sortowanie przez wstawianie Sortowanie bablekowe Sortowanie koktajlowe Sortowanie przez scalanie Sortowanie przez zlicznie Właściwy wybór to: sortowanie przez zliczanie Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 76 / 79

Sortowanie pozycyjne - analiza Załóżmy, że wybranym sortowaniem pomocniczym jest sortowanie przez zliczanie. Sortowanie przez zliczanie pracuje w czasie Θ(n + k), aby posortować n liczb z zakresu od 0 do k 1. Jeśli b-bitowe słowo (b-bitowa liczba) zostanie podzielone na r-bitowe kawałki, to każdy przebieg sortowania przez zlicznie będzie wykonany w czsie Θ(n + 2 r ). Ponieważ w sortowaniu pozycyjnym będziemy mieli b/r przebiegów, to czas wykonania sortowania będzie: T (n, b) = Θ( b r (n + 2r )) Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 77 / 79

Wybór T (n, b) = Θ( b r (n + 2r )) Aby algorym sortowania pozycyjnego pracował szybko (tzn. w czasie liniowym), należy odpowiednio dobrze dobrać r. W szczególności duże r oznacza, że będzie tylko kilka przebiegów. Należy zwrócić uwagę, aby r nie było zbyć duże, gdyż jeśli r > log 2 (n), to czas sortowania pomocniczego (przez zliczanie) i potrzebna mu pamięć będzie zbyt duża. Aby zminimalizować T (n, b), należy wybrać r = log 2 (n), co implikuje T (n, b) = Θ(b n/log 2 (n))). Powyższe r można uzyskać poprzez zróżniczkowanie fukcji T (n, b) względem zmiennej r i podstawieniu pod powstała funkcję wartości 0. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 78 / 79

Uwagi końcowe W praktyce sortowanie pozycyjne jest bardzo dobre dla dużych danych. Przykładowo dla liczb 32-bitowych przy sortowaniu 2000 danych sortowanie pozycyjne wykona (b n/log 2 (n))) = 32 2000/log 2 (2000) 3 2000 operacji. Dla porównania, sortowanie szybkie wykona n log 2 (n) = 2000 log 2 (2000) 11 2000 operacji. Bożena Woźna-Szcześniak (AJD) Algorytmy i Struktury Danych. Wykład 5 79 / 79