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

Podobne dokumenty
Strategia "dziel i zwyciężaj"

Wstęp do programowania

Wstęp do informatyki- wykład 12 Funkcje (przekazywanie parametrów przez wartość i zmienną)

Podstawy algorytmiki i programowania - wykład 3 Funkcje rekurencyjne Wyszukiwanie liniowe i binarne w tablicy

Algorytm selekcji Hoare a. Łukasz Miemus

Wstęp do programowania

Podstawy algorytmiki i programowania - wykład 2 Tablice dwuwymiarowe cd Funkcje rekurencyjne

Wstęp do informatyki- wykład 7

Podstawy algorytmiki i programowania - wykład 5 C-struktury cd.

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

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 )

Sortowanie. LABORKA Piotr Ciskowski

Programowanie Proceduralne

Algorytmy sortujące i wyszukujące

Programowanie w VB Proste algorytmy sortowania

Wstęp do informatyki- wykład 6

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

Sortowanie przez scalanie

Algorytmy i Struktury Danych.

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

Podstawy algorytmiki i programowania - wykład 1 Tablice powtórzenie Tablice znaków Tablice dwuwymiarowe

Wstęp do informatyki- wykład 11 Funkcje

Wstęp do informatyki- wykład 8 Pętla while, do while,for -pętla w pętli- przykłady Operator rzutowania Manipulatory

Wstęp do informatyki- wykład 9 Funkcje

(3 kwiecień 2014) Marika Pankowska Kamila Pietrzak

Analiza algorytmów zadania podstawowe

Wstęp do programowania INP001213Wcl rok akademicki 2018/19 semestr zimowy. Wykład 4. Karol Tarnowski A-1 p.

Wstęp do Informatyki

wykład IV uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C, a C++. wykład IV dr Jarosław Mederski Spis Język C++ - wstęp

np. dla p=1 mamy T1(N) N/2 średni czas chybionego wyszukiwania z prawdopodobieństwem q:

Wstęp do informatyki- wykład 5 Instrukcja selekcji if-else Operatory arytmetyczne i logiczne

Sortowanie - wybrane algorytmy

Algorytmika i programowanie. Wykład 2 inż. Barbara Fryc Wyższa Szkoła Informatyki i Zarządzania w Rzeszowie

Informacje wstępne #include <nazwa> - derektywa procesora umożliwiająca włączenie do programu pliku o podanej nazwie. Typy danych: char, signed char

Algorytmy. 1. Sortowanie 2. Statki i okręty. programowanie cz.7. poniedziałek, 2 marca 2009

Kontrola przebiegu programu

Tablice. Monika Wrzosek (IM UG) Podstawy Programowania 96 / 119

Podstawy algorytmiki i programowania - wykład 4 C-struktury

Wstęp do programowania

Wstęp do informatyki- wykład 7

Liczby całkowite i rzeczywiste

Wstęp do programowania

Rozwiązanie. #include <cstdlib> #include <iostream> using namespace std;

Wstęp do informatyki- wykład 10 Funkcje (przekazywanie parametrów przez wartość i zmienną)

Anna Sobocińska Sylwia Piwońska

Wstęp do informatyki- wykład 9 Pętla while, do while,for -pętla w pętli- przykłady Funkcje

Programowanie w C++ Wykład 5. Katarzyna Grzelak. 16 kwietnia K.Grzelak (Wykład 1) Programowanie w C++ 1 / 27

Struktury Danych i Złożoność Obliczeniowa

Programowanie Procedurale

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

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

Wykład I. Programowanie II - semestr II Kierunek Informatyka. dr inż. Janusz Słupik. Wydział Matematyki Stosowanej Politechniki Śląskiej

Efektywna metoda sortowania sortowanie przez scalanie

Wstęp do programowania

Podstawy Programowania

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

Matematyczne Podstawy Informatyki

REKURENCJA W JĘZYKU HASKELL. Autor: Walczak Michał

Programowanie i struktury danych

Wybrane algorytmy tablicowe

Rekurencja. Przygotowała: Agnieszka Reiter

Opis zagadnieo 1-3. Iteracja, rekurencja i ich realizacja

Wstęp do informatyki- wykład 1

Zajęcia nr 2 Programowanie strukturalne. dr inż. Łukasz Graczykowski mgr inż. Leszek Kosarzewski Wydział Fizyki Politechniki Warszawskiej

Metodyki i Techniki Programowania 2

Zadanie 1 Przygotuj algorytm programu - sortowanie przez wstawianie.

wykład V uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C++ klasy i obiekty wykład V dr Jarosław Mederski Spis Język C++ - klasy

Informatyka A. Algorytmy

8. Wektory. Przykłady Napisz program, który pobierze od użytkownika 10 liczb, a następnie wypisze je w kolejności odwrotnej niż podana.

12. Rekurencja. UWAGA Trzeba bardzo dokładnie ustalić <warunek>, żeby mieć pewność, że ciąg wywołań się zakończy.

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

ZASADY PROGRAMOWANIA KOMPUTERÓW ZAP zima 2015

Ćwiczenie 7 z Podstaw programowania. Język C++, programy pisane w nieobiektowym stylu programowania. Zofia Kruczkiewicz

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

Wykład 5. Sortowanie w czasie liniowologarytmicznym

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

Programowanie - wykład 4

Programowanie komputerowe. Zajęcia 1

Wstęp do programowania

Algorytmy sortujące. sortowanie kubełkowe, sortowanie grzebieniowe

ALGORYTMY I STRUKTURY DANYCH

Sortowanie przez wstawianie Insertion Sort

Podstawy Programowania Podstawowa składnia języka C++

void Pobierz(Student &a); void Wypisz(Student a); void Ustaw_zaliczenia(Student t[],int r); void Wypisz_najlepszych(Student t[],int r, float prog);

Programowanie w C++ Wykład 2. Katarzyna Grzelak. 4 marca K.Grzelak (Wykład 1) Programowanie w C++ 1 / 44

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

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

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

tablica: dane_liczbowe

Podstawy informatyki. Informatyka stosowana - studia niestacjonarne. Grzegorz Smyk. Wydział Inżynierii Metali i Informatyki Przemysłowej

Pytanie 1. Pytanie 2. Pytanie 3 WOJEWÓDZKI KONKURS INFORMATYCZNY. Treść pytania

Wstęp do programowania

Laboratorium nr 7 Sortowanie

Część 4 życie programu

Liczby pseudolosowe. #include <stdio.h> #include <stdlib.h> int main() { printf("%d\n", RAND_MAX); return 0; }

PDF stworzony przez wersję demonstracyjną pdffactory Pro Program 15

Programowanie w C++ Wykład 2. Katarzyna Grzelak. 5 marca K.Grzelak (Wykład 1) Programowanie w C++ 1 / 41

Program 14. #include <iostream> #include <ctime> using namespace std;

Programowanie C++ Wykład 2 - podstawy języka C++ dr inż. Jakub Możaryn. Warszawa, Instytut Automatyki i Robotyki

Transkrypt:

1 Podstawy algorytmiki i programowania - wykład 6 Sortowanie- algorytmy Treści prezentowane w wykładzie zostały oparte o: S. Prata, Język C++. Szkoła programowania. Wydanie VI, Helion, 2012 www.cplusplus.com Jerzy Grębosz, Opus magnum C++11, Helion, 2017 B. Stroustrup, Język C++. Kompendium wiedzy. Wydanie IV, Helion, 2014 S. B. Lippman, J. Lajoie, Podstawy języka C++, WNT, Warszawa 2003.

2 Sortowanie szybkie - quicksort Strategia "dziel i zwyciężaj": polega na dzieleniu problemu na kilka mniejszych podproblemów podobnych do początkowego problemu. Problemy te rozwiązywane są rekurencyjnie, a następnie rozwiązania wszystkich podproblemów są łączone w celu utworzenia rozwiązania całego problemu. Szybkie sortowanie (ang. quicksort) to jeden z popularnych algorytmów sortowania działających na zasadzie "dziel i zwyciężaj" Średnia złożoność obliczeniowa tego algorytmu jest rzędu O(n log n), pesymistyczna O(n 2 ). Quicksort jest powszechnie używany. Jego implementacje znajdują się w bibliotekach standardowych wielu środowisk programowania.

Sortowanie szybkie quicksort - algorytm ALGORYTM Quicksort polega na dzieleniu tablicy na dwie części, a następnie rekurencyjnym sortowaniu każdej z nich. Tablica jest dzielona przez umieszczenie wszystkich elementów mniejszych niż pewien wybrany element (element rozdzielający) przed tym elementem oraz wszystkich elementów które są od niego większe za nim. Elementem rozdzialającym, progowym (ang. pivot ) może być dowolny element np. element pierwszy, środkowy albo losowy. Potem sortuje się osobno obie części tablicy - podtablice. Rekurencja kończy się, gdy otrzymana z podziału podtablica jest jednoelementowa (czyli nie wymaga już sortowania). 3

Sortowanie szybkie quicksort - algorytm 4 Ogólna strategia podziału tablicy: 1. wybieramy pivot, 2. przeglądamy tablicę od jej lewego końca, aż znajdziemy element większy niż pivot 3. przeglądamy tablicę od jej prawego końca, aż znajdziemy element mniejszy niż pivot 4. oba elementy, które zatrzymują przeglądanie tablicy, są na pewno nie na swoich miejscach w tablicy, więc je zamieniamy ze sobą

Sortowanie szybkie quicksort - przykład 5 Rozważmy tablicę KROK 1: Wyznaczamy element rozdzielający pivot element środkowy, Ustawiamy liczniki i na pierwszy element tablicy, natomiast j na ostatni l = 0 1 2 3 4 5 6 p = 7 65 21 48 87 5 59 74 x=a[(0+7)/2]=a[3]=48 element tablicy: l = 0 1 2 3 4 5 6 p = 7 32 65 21 48 87 5 59 74 i j

Sortowanie szybkie quicksort - przykład 6 KROK 2: W kolejnym kroku szukamy pierwszej liczby z lewej strony tablicy poruszając się licznikiem i ku wartości pivot, która jest nie mniejsza niż pivot (czyli dopóki elementy są mniejsze od x to zwiększamy i) oraz pierwszej liczby z prawej strony, która jest nie większa niż pivot (dopóki elementy są większe od x to zmniejszamy j). Stan liczników po wyszukaniu odpowiednich liczb: l = 0 1 2 3 4 5 6 p = 7 32 65 21 48 87 5 59 74 i i j j j

7 Sortowanie szybkie quicksort - przykład Jeśli indeksy się nie minęły (czyli i<=j), to dokonujemy zamiany elementów : 65 <-> 5, a następnie zwiększamy i ( i++), i zmniejszamy j (j--): l = 0 1 2 3 4 5 6 p = 7 32 65 21 48 87 5 59 74 i j Otrzymujemy l = 0 1 2 3 4 5 6 p = 7 32 5 21 48 87 65 59 74 i j Czynności powtarzamy do momentu minięcia się liczników:

Sortowanie szybkie quicksort - przykład KROK 2: Ponownie szukamy pierwszej liczby z lewej strony tablicy która jest nie mniejsza niż pivot (czyli dopóki elementy są mniejsze od x to zwiększamy i) oraz pierwszej liczby z prawej strony, która jest nie większa niż pivot (dopóki elementy są większe od x to zmniejszamy j). l = 0 1 2 3 4 5 6 p = 7 32 5 21 48 87 65 59 74 i,j Sprawdzamy czy i<=j (czy się nie minęły) u nas i=j=3 zatem wymieniamy 48 z 48 i robimy i++, j-- l = 0 1 2 3 4 5 6 p = 7 32 5 21 48 87 65 59 74 j i 8

9 Sortowanie szybkie quicksort - przykład Indeksy i i j się minęły- otrzymaliśmy podzial na podciągi zielony elementy<=x niebieski elementy >=x i być może środkowy : elementy =x l = 0 1 2 3 4 5 6 p = 7 32 5 21 48 87 65 59 74 j i KROK 3. W kolejnym kroku wykonujemy sortowanie dwóch tablic tab[l,j],tab[i,p ]osobno (wywołanie rekurencyjne), o ile nie są one jednoelementowe, czyli l<j i i<p Quicksort(0,2,a) Quicksort(4,7,a) l = 0 1 p=2 32 5 21 i j l=4 5 6 p = 7 87 65 59 74 i j

Sortowanie szybkie quicksort - przykład l = 0 1 p=2 32 5 21 Quicksort(0,2,a) i j KROK 1. i=l=0 j=p=2, x=a[(0+2)/2]=a[1]=5 KROK 2: dopóki elementy są mniejsze od x to zwiększamy i dopóki elementy są większe od x to zmniejszamy j l = 0 1 p=2 32 5 21 i j j Sprawdzamy czy i<=j, wymieniamy 32 z 5 i robimy i++, j-- l = 0 1 p=2 5 32 21 j i 10

11 Sortowanie szybkie quicksort - przykład Indeksy się minęły- otrzymaliśmy podział na podciągi, zatem KROK 3: l = 0 1 p=2 5 32 21 j i l=j tablica 1 elementowa- nie ma już czego sortować i<p wywołujemy quicksort rekrencyjnie Quicksort(1,2,a) KROK 1: i=l=1 j=p=2 x=a[(1+2)/2]=a[1]=32 KROK 2: l=1 p=2 32 21 i j dopóki elementy są mniejsze od x to zwiększamy i dopóki elementy są większe od x to zmniejszamy j l=1 p=2 32 21 i j

Sortowanie szybkie quicksort - przykład 12 Sprawdzamy czy i<=j (czy się nie minely), wymieniamy 32 z 21 i robimy i++, j-- l=1 p=2 21 32 j i Indeksy się minęły- otrzymaliśmy podział na podciągi KROK 3: l=j tablica 1 elementowa- nie ma już czego sortować i=p tablica 1 elementowa- nie ma już czego sortować Zatem lewa podtablica jest już posortowana: 0 1 2 5 21 32

Sortowanie szybkie quicksort - przykład Teraz prawa podtablica Quicksort(4,7,a) l=4 5 6 p = 7 87 65 59 74 i j KROK 1:i=l=4 j=p=7 x=a[(4+7)/2]=a[5]=65 KROK 2: dopóki elementy są mniejsze od x to zwiększamy i dopóki elementy są większe od x to zmniejszamy j l=4 5 6 p = 7 87 65 59 74 i j j 13

Sortowanie szybkie quicksort - przykład Sprawdzamy czy i<=j wymieniamy 87 z 59 i robimy i++, j-- 14 i<=j zatem ponownie KROK 2: l=4 5 6 p = 7 59 65 87 74 i j dopóki elementy są mniejsze od x to zwiększamy i dopóki elementy są większe od x to zmniejszamy j l=4 5 6 p = 7 59 65 87 74 i j Sprawdzamy czy i<=j wymieniamy 65 z 65 i robimy i++, j--

15 Otrzymujemy Sortowanie szybkie quicksort - przykład l=4 5 6 p = 7 59 65 87 74 j i Indeksy się minęły- otrzymaliśmy podział na podciągi KROK 3: l=j tablica 1 elementowa- nie ma już czego sortować i<p wywołujemy quicksort rekurencyjnie Quicksort(6,7,a) l=6 p = 7 87 74 i j KROK 1:i=l=6 j=p=7 x=a[(6+7)/2]=a[6]=87 KROK 2: dopóki elementy są mniejsze od x to zwiększamy i dopóki elementy są większe od x to zmniejszamy j l=6 p = 7 87 74 i j

Sortowanie szybkie quicksort - przykład 16 Sprawdzamy czy i<=j wymieniamy 87 z 74 i robimy i++, j-- l=6 p = 7 74 87 j i Indeksy się minęły- otrzymaliśmy podział na podciągi KROK 3: l=j tablica 1 elementowa- nie ma już czego sortować i=p tablica 1 elementowa- nie ma już czego sortować Zatem prawa podtablica jest posortowana l=4 5 6 p = 7 59 65 74 87

Sortowanie szybkie quicksort - przykład 17 PODSUMOWANIE: drzewo wywołań: Quicksort(0,7,a) Quicksort(0,2,a) Quicksort(4,7,a) Quicksort(1,2,a) Quicksort(6,7,a)

Sortowanie szybkie quicksort - implementacja #include <iostream> #include <string> #include <ctime> using namespace std; const int NMAX=20; // stała globalna określająca // max rozmiar tablic //QuickSort- szybkie sortowanie void quicksort(int l, int p, int a[]) { //krok 1 int i, j, pom; //punkt progowy (pivot) int x = a[(l+p)/2]; i = l; //i ustawiamy na lewym j = p; // j na prawym 18

Sortowanie szybkie quicksort - implementacja 19 //dopóki indeksy się nie minęły while(i<=j) { // krok 2 //najpierw z lewej strony,szukamy najmniejszego // indeksu i, takiego, ze a[i]>=x //czyli dopóki elementy są mniejsze od x to i++ while (a[i] < x) i++; //teraz od prawej: szukamy największego indeksu // j, takiego, że a[i]<=x //czyli dopóki elementy są większe od x to // zmniejszamy j while (a[j] > x) j--;

Sortowanie szybkie quicksort - implementacja 20 // jeśli i<=j, to przestawiamy elementy //a[i] z a[j] i i++, j-- if(i<=j) { pom = a[i]; a[i] = a[j]; a[j] = pom; i++; j--; } //jesli nadal i<=j to wroc do kroku 2, // w przeciwnym przypadku do kroku 3 }//while

Sortowanie szybkie quicksort - implementacja 21 //krok 3 // otrzymaliśmy podział na 3 podciągi // a[k]<=x dla l<=k<=j // a[k]= x dla j+1<=k<=i-1 // a[k]>=x dla i<=k<=p //jeśli podtablice nie są jednoelementowe if (l<j) quicksort(l, j, a);//wywołanie rekurencyjne if (i<p) quicksort(i, p, a);//wywołanie rekurencyjne }//quicksort

22 Sortowanie szybkie quicksort - implementacja //WYSWIETLANIE TABLICY //f-cja wyswietla na standardowym wyjsciu tablice // o n-elementach:[a_0,a_1,,a_{n-1}] void printtab(int n, int t[]) { cout<<"["; for (int i=0; i < n; i++) { cout<<t[i]; //jeśli nie jest to ostatni elem,to wyswietlamy, if (i < n-1) cout<<","; } cout<<"]"; }

23 Sortowanie szybkie quicksort - implementacja //POBIERANIE TABLICY //funkcja pobierajaca od uzytkownika rozmiar n, // a następnie elementy tablicy void pobtab(int &n, int t[] ) { //w pętli zaporowej pob.n z przedzialu [1, NMAX] do{ cout << "Podaj rozmiar tablicy: "; cin >> n; }while(n < 1 n > NMAX); //pobieramy elementy tablicy: t[0],...,t[n-1] for(int i=0; i < n; i++) { cout << "Podaj "<<i<<" el tabl: "; cin >> t[i]; } }

Sortowanie szybkie quicksort - implementacja //GENEROWANIE LOSOWE TABLICY //funkcja generuje losowo rozmiar tablicy, //a nastepnie generuje losowo jej elementy z // przedzialu [0,9] /*int rand (void); generuje liczbe losowa z przedziału 0 do RAND_MAX. v1 = rand() % 100; // v1 z przedziału 0 do 99 v2 = rand() % 100 + 1; // v2 z przedziału 1 do 100*/ void gentablos (int &nmax, int t[] ) { //Dynamiczna wielkosc tablicy: nmax = rand()%nmax + 1; //Wypelnienie tablicy liczbami (pseudo)losowymi for (int i=0; i<nmax; i++) t[i] = rand()%10; } 24

25 Sortowanie szybkie quicksort - implementacja //CZY POSORTOWANA /*fcja sprawdzajaca czy tablica przekazana jako parametr f-cji jest posortowana */ bool jestsort(int n, int t[] ) { for (int i=0; i < n-1; i++) if (t[i] > t[i+1]) return false; return true; }

Sortowanie szybkie quicksort - implementacja int main() { //1sp. sami deklarujemy testowa tablice cout<<"quicksort dla przykladowej tablicy\n"; int a[]={32,65,21,48,87,5,59,74}; printtab(8,a);//wyswietlamy tablica cout << " -> "; quicksort(0,7,a);//sortujemy printtab(8,a);//wyswietlamy tablica cout << endl; //sprawdzamy czy posortowana cout<<(jestsort(8,a)?"ok":"blad")<< endl<<endl; /*quicksort dla przykladowej tablicy: [32,65,21,48,87,5,59,74] -> [5,21,32,48,59,65,74,87] ok */ 26

27 Sortowanie szybkie quicksort - implementacja //2sp dane pobieramy od uzytkownika cout<<"dane do sortowania od uzytkownika:"<<endl; int tab[nmax]; int n; pobtab(n,tab); //pobieramy tablice printtab(n,tab); //wydruk przed cout<<" -> "; quicksort(0,n-1,tab); //sortowanie printtab(n,tab); //wydruk po cout<<endl; //spr. czy posortowana cout<<(jestsort(n,tab)?"ok":"blad")<< endl<<endl;

28 Sortowanie szybkie quicksort - implementacja //3 sposob dane generujemy losowo cout<<"losowo generujemy 10 tablic:"<<endl; // Ustawia punkt startowy //generatora pseudolosowego srand( time( NULL ) ); int t[nmax] = {0}; //tworzymy i od razu //zerujemy tablice NMAX elementowa int nmax ; //zmienna na rzeczywisty rozmiar // tablicy 0<nmax<=NMAX

29 } Sortowanie szybkie quicksort - implementacja for (int i=0; i<10; i++) { gentablos(nmax,t) ; //generujemy tablice losowo printtab(nmax, t); //wydruk przed quicksort(0, nmax-1, t);//sortowanie tablicy: cout<<" -> "; printtab(nmax, t); //wydruk po cout<<endl; if (jestsort(nmax,t)) cout<<"ok\n"; else cout<<"blad\n"; } return 0;

30 Sortowanie szybkie quicksort - implementacja Sortowanie szybkie zostało wynalezione przez angielskiego informatyka, profesora Tony'ego Hoare'a w latach 60-tych ubiegłego wieku. W przypadku typowym algorytm ten jest najszybszym algorytmem sortującym z klasy złożoności obliczeniowej O(n log n) - stąd pochodzi jego popularność w zastosowaniach. Należy jednak pamiętać, iż w pewnych sytuacjach (zależnych od sposobu wyboru pivotu oraz niekorzystnego ułożenia danych wejściowych np. gdy dane wejściowe są już posortowane, lub gdy są uporządkowane w odwrotnej kolejności) klasa złożoności obliczeniowej tego algorytmu może się degradować do O(n 2 ), co więcej, poziom wywołań rekurencyjnych może spowodować przepełnienie stosu i zablokowanie komputera.