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

Podobne dokumenty
Laboratorium nr 7 Sortowanie

Algorytm selekcji Hoare a. Łukasz Miemus

WYKŁAD 8. Funkcje i algorytmy rekurencyjne Proste przykłady. Programy: c3_1.c..., c3_6.c. Tomasz Zieliński

WYKŁAD 10. Zmienne o złożonej budowie Statyczne i dynamiczne struktury danych: lista, kolejka, stos, drzewo. Programy: c5_1.c, c5_2, c5_3, c5_4, c5_5

Strategia "dziel i zwyciężaj"

Algorytmy sortujące i wyszukujące

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

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

Instrukcja wyboru, pętle. 2 wykład. Podstawy programowania - Paskal

funkcje rekurencyjne Wykład 12. Podstawy programowania (język C) Funkcje rekurencyjne (1) Funkcje rekurencyjne (2)

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

Programowanie w VB Proste algorytmy sortowania

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

Wykład 7 Abstrakcyjne typy danych słownik (lista symboli)

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

Wykład 5_2 Algorytm ograniczania liczby serii za pomocą kopcowego rozdzielania serii początkowych

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

Tablice i struktury. czyli złożone typy danych. Programowanie Proceduralne 1

Algorytmy i złożoności. Wykład 3. Listy jednokierunkowe

Wykład 6_1 Abstrakcyjne typy danych stos Realizacja tablicowa i za pomocą rekurencyjnych typów danych

E S - uniwersum struktury stosu

Sortowanie przez wstawianie Insertion Sort

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

TABLICE W JĘZYKU C/C++ typ_elementu nazwa_tablicy [wymiar_1][wymiar_2]... [wymiar_n] ;

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

1. Nagłówek funkcji: int funkcja(void); wskazuje na to, że ta funkcja. 2. Schemat blokowy przedstawia algorytm obliczania

struct Student { char nazwisko[30]; int wiek; float ocena; }; #define MAX_ROZMIAR 3 Student lista_studentow[max_rozmiar];

tablica: dane_liczbowe

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

Wstęp do programowania

Analiza algorytmów zadania podstawowe

PDF stworzony przez wersję demonstracyjną pdffactory Pro Program 15

Sortowanie danych. Jolanta Bachan. Podstawy programowania

Wskaźniki. Programowanie Proceduralne 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 )

Kontrola przebiegu programu

Tablice mgr Tomasz Xięski, Instytut Informatyki, Uniwersytet Śląski Katowice, 2011

Programowanie Proceduralne

Sortowanie. LABORKA Piotr Ciskowski

Metodyki i Techniki Programowania 2

Pola i metody statyczne

Algorytmy sortowania w języku C. Autor: mgr inż. Sławomir Samolej. Zagadnienie 1. (Sortowanie)

Sortowanie - wybrane algorytmy

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

Języki programowania. Przetwarzanie tablic znaków. Część druga. Autorzy Tomasz Xięski Roman Simiński

znalezienia elementu w zbiorze, gdy w nim jest; dołączenia nowego elementu w odpowiednie miejsce, aby zbiór pozostał nadal uporządkowany.

Wskaźniki. Przemysław Gawroński D-10, p marca Wykład 2. (Wykład 2) Wskaźniki 8 marca / 17

Kolokwium ze wstępu do informatyki, I rok Mat. (Ściśle tajne przed godz. 10 : grudnia 2005.)

Proste algorytmy w języku C

Dynamiczny przydział pamięci w języku C. Dynamiczne struktury danych. dr inż. Jarosław Forenc. Metoda 1 (wektor N M-elementowy)

Algorytmy i Struktury Danych.

Podstawy Programowania C++

Funkcja (podprogram) void

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

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

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

Podstawy programowania

Metody Metody, parametry, zwracanie wartości

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

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

4. Tablica dwuwymiarowa to jednowymiarowa tablica wskaźników do jednowymiarowych tablic danego typu.

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

Proste algorytmy w języku C

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

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

Algorytmy i Struktury Danych

Wykład 3 Składnia języka C# (cz. 2)

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

Programowanie Proceduralne

Etap 2 - Budowa interfejsu. typedef struct ELEMENT* stos; struct ELEMENT { dane Dane; stos Nastepny; }; struct kolejka { stos Poczatek, Koniec; };

Co nie powinno być umieszczane w plikach nagłówkowych:

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

Podstawy programowania w języku C i C++

Podstawy programowania. Wykład: 8. Wskaźniki. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

KURS C/C++ WYKŁAD 8. Deklaracja funkcji informuje komplilator jaką wartość funkcja będzie zwracała i jakiego typu są jej argumenty.

Języki programowania obiektowego Nieobiektowe elementy języka C++

5 Przygotował: mgr inż. Maciej Lasota

Wykład 1 Wprowadzenie do algorytmów. Zawartość wykładu 1. Wstęp do algorytmów i struktur danych 2. Algorytmy z rozgałęzieniami.

Stałe, tablice dynamiczne i wielowymiarowe

Programowanie dynamiczne

Wykład 2. Poprawność algorytmów

Dynamiczny przydział pamięci (język C) Dynamiczne struktury danych. Sortowanie. Klasyfikacja algorytmów sortowania. Algorytmy sortowania

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

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

Co to jest sterta? Sterta (ang. heap) to obszar pamięci udostępniany przez system operacyjny wszystkim działającym programom (procesom).

W języku C dostępne są trzy instrukcje, umożliwiające tworzenie pętli: for, while oraz do. for (w1;w2;w3) instrukcja

PODSTAWY INFORMATYKI 1 PRACOWNIA NR 6

Lab 9 Podstawy Programowania

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

Wykład VII. Programowanie. dr inż. Janusz Słupik. Gliwice, Wydział Matematyki Stosowanej Politechniki Śląskiej. c Copyright 2014 Janusz Słupik

Informatyka wprowadzenie do algorytmów (II) dr hab. inż. Mikołaj Morzy

WYKŁAD 4, 5 i 6. Wprowadzenie do języka C Mój pierwszy, drugi,..., n-ty program w języku C. Programy: c1_1.c... c1_9.c.

wykład II uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C - funkcje, tablice i wskaźniki wykład II dr Jarosław Mederski Spis

Tablice cz. I Tablice jednowymiarowe, proste operacje na tablicach

Tablice deklaracja, reprezentacja wewnętrzna

Algorytm. a programowanie -

7. Pętle for. Przykłady

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

Wstęp do programowania 1

// Liczy srednie w wierszach i kolumnach tablicy "dwuwymiarowej" // Elementy tablicy są generowane losowo #include <stdio.h> #include <stdlib.

Transkrypt:

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

/* Przyklad 4.1 - SORTOWANIE TABLIC - metoda najprostsza */ #include <stdio.h> #define ROZMIAR 11 void sortuj( int dane[ ], int N ); // funkcja sortująca int minim( int dane[ ], int start, int N ); // funkcja znajdowania min /* program glowny ---------------------------------------------------------------- */ void main() int tab[ ROZMIAR ] = 0, 9, 2, 7, 4, 5, 6, 3, 8, 1, 10 ; int i; sortuj( tab, ROZMIAR ); /* uporzadkuj dane ------------------- */ for( i=0; i < ROZMIAR; i++) /* wydrukuj wynik sprzatania -------*/ printf(" %d \n", tab[ i ] ); /* funkcje pomocnicze ----------------------------------------------------------- */ void sortuj( int dane[ ], int N ) int x, i, j; for( i=0; i < N-1; i++ ) // powtarzaj dla i = 0, 1, 2,..., N-2 // znajdz indeks j próbki o min wartości, j = minim( dane, i+1, N ); // leżącej powyżej dane[i] if ( dane[ j ] < dane[ i ]) // zamien miejscami dane[i] i dane[j], // jesli dane[ j ] < dane[ i ] x = dane[ i ]; dane[ i ] = dane[ j ]; dane[ j ] = x;

/* ---------------------------------------------------------------------------------------- */ /* znajdz indeks probki, i = start,..., N */ /* dla ktorej wartosc dane[ i ] jest najmniejsza */ /* ---------------------------------------------------------------------------------------- */ int minim( int dane[ ], int start, int N ) int i, imin, vmin; imin = start; vmin = dane[ start ]; // indeks minimum = start // wartość minimum = dane[start] for( i = start+1; i < N; i++ ) if (vmin > dane[i] ) imin=i; vmin = dane[ i ]; // kolejny element tablicy // jeśli mniejsze od min, // to będzie nowym minimum return( imin );

/* Przyklad 4.2 - SORTOWANIE TABLIC - metoda babelkowa */ #include <stdio.h> #define ROZMIAR 11 /* liczba elementów tablicy */ #define NIE 0 #define TAK 1 void sortuj( int dane[ ], int N ); /* funkcja sortująca */ /* program glowny ---------------------------------------------------------------- */ void main() int tab[ ROZMIAR ] = 0, 9, 2, 7, 4, 5, 6, 3, 8, 1, 10 ; int i; sortuj( tab, ROZMIAR ); /* uporzadkuj dane ------------ */ for( i=0; i < ROZMIAR; i++) /* wydrukuj wynik sprzatania */ printf(" %d \n", tab[ i ] ); /* Funkcja pomocnicza----------------------------------------------------------- */ void sortuj( int dane[ ], int N ) int x, i, j, powtorz = TAK; for( i=0; (i < N-1) && powtorz==tak; i++ ) // fale bąbli powtorz = NIE; for( j=0; j < N-i-1; j++) // jesli niepoprawna kolejność if (dane[ j ] > dane[ j+1 ]) // to bąbel, powtorz = TAK; // czyli zamiana miejscami x = dane[ j ]; dane[j] = dane[j+1]; dane[j+1] = x;

/* OPIS PROGRAMU 1) Algorytm składa się z tzw. fal bąbli. 2) W każdej fali bierze się po kolei dwa sąsiednie elementy, tzn. 0 i 1, 1 i 2, 2 i 3,... i zamienia się je miejscami ( bąbel!), jeśli element o mniejszym indeksie ma większą wartość. 3) Po każdej fali największy element zostaje przesunięty na koniec zbioru. Dlatego każda następna fala jest o jeden element krótsza. 4) Jeśli w jakiejś fali nie wstąpił żaden bąbel to znaczy, że wszystkie elementy są uporządkowane od najmniejszego do największego. 5) Dlatego kolejną falę przeprowadza się tylko wtedy kiedy w poprzedniej wystąpił bąbel oraz nie wszystkie fale zostały wykonane (dla zbioru N elementowego wykonuje się N-1 fal). 6) Przed dojściem do elementu największego (dryblasa) bąblowanie prowadzi do wstępnego porządkowania elementów mniejszych. Potem dryblas ze wszystkimi wygrywa i przesuwa się na koniec zbioru. 7) Jeśli zbiór jest uporządkowany, to zostaje wykonana tylko jedna fala bąbli. */

/* Przyklad 4.3a - SORTOWANIE TABLIC */ /* - metoda szybka - ang. QuickSort */ /* - wersja rekurencyjna */ #include <stdio.h> #define ROZMIAR 11 // liczba danych w tablicy void sortuj( int dane[ ], int dol, int gora ); // funkcja sortująca void wydruk( int dane[ ], int N ); // wydruk tablicy /* program glowny --------------------------------------------------------- */ void main() // int tab[ ROZMIAR ] = 0,9,2,7,4,5,6,3,8,1,10 ; /* ver.1 */ int tab[ ROZMIAR ] = 25,57,48,37,12,92,86,33 ; /* ver.2 */ sortuj( tab, 0, ROZMIAR-1 ); wydruk( tab, ROZMIAR ); /* Funkcja wydruku ----------------------------------------------------- */ void wydruk( int dane[ ], int N ) int i; for( i=0; i < N; i++) printf(" %2d ", dane[ i ] );

/* Funkcja sortujaca --------------------------------------------------------------- */ // Sortuj elementy tablicy dane[], zaczynając od tego o indeksie dol, // a kończąc na tym o indeksie gora void sortuj( int dane[ ], int dol, int gora ) int id, ig; // robocze indeksy id (dolny -->) i górny ig ( <-- ig) int a, x; // id idzie do góry, zaś ig - do dołu id = dol; ig = gora; a = dane[ dol ]; // inicjalizacja id, ig, a while ( id < ig ) // podzial // zbioru while ( (dane[ id ] <= a) && (id < gora) ) id++; // na while ( (a < dane[ ig ] ) && (dol < ig ) ) ig--; // elementy if ( id < ig ) // mniejsze // i x = dane[ id ]; // wieksze dane[ id ] = dane[ ig ]; // od dane[ ig ] = x; // elementu // pierwszego // dane[ dol ] = dane[ ig ]; // dane[ ig ] = a; // if ( dol < ig-1 ) sortuj( dane, dol, ig-1 ); // teraz sortuj poniżej if ( ig+1 < gora ) sortuj( dane, ig+1, gora ); // a potem - powyżej /* OPIS PROGRAMU 1) Indeks id idzie do góry, kiedy poniżej zostaje element mniejszy lub równy od elementu pierwszego a=dane[dol] oraz kiedy są jeszcze elementy powyżej. W pewnym momencie blokuje się na elemencie większym od pierwszego. 2) Indeks ig idzie do dołu, kiedy powyżej zostaje element większy od elementu pierwszego a=dane[dol] oraz kiedy są jeszcze elementy poniżej. W pewnym momencie blokuje na elemencie mniejszym od pierwszego. 3) W tym momencie następuje zamiana miejscami elementów blokujących : za duży jest przesunięty do góry, a za mały - na dól. 4) Po odblokowaniu, indeksy id i ig ponownie przesuwają się dopóki jest spełniony warunek id < ig. 5) Kiedy nie jest już on spełniony, indeks ig pokazuje na ostatni element mniejszy od pierwszego. Dlatego następuje wówczas zamiana miejscami elementów dane[dol] i dane[ig] 6) Następnie funkcja wykonuje się rekurencyjnie na elementach o indeksach mniejszych od ig [dol, ig-1] oraz na elementach większych od ig [ig+1, gora]. */

/* Przyklad 4.3b - SORTOWANIE TABLIC */ /* metoda szybka ang. QuickSort */ // Wersja nierekurencyjna z tablicy jako stosu (statycznie) // UWAGA: analiza programu dopiero po wykładzie nr 10 #include <stdio.h> #include <conio.h> #include <stdlib.h> /* definicja strukur danych --------------------------------------------------------- */ #define ROZMIAR 11 #define MAXSTOS 1000 // liczba elementów tablicy // wielkość stosu programowego #define TAK 1 #define NIE 0 struct typdg // definicja nowego typu typdg zmiennych // każda zmienna złożona tego typu int dol; // będzie się składała z dwóch liczb int gora; // np. struct typdg x; // deklaracja ; // x.dol = 0; x.gora = 10; // inicjalizacja struct typstos // definicja nowego typu typstos zmiennych // np. struct typstos x; int top; // x.top = -1; struct typdg granice[ MAXSTOS ]; // x.granice[0].dol = 0; ; // x.granice[0].gora = 0; /* deklaracja sposobu wywołania funkcji -------------------------------------- */ int pustystos( struct typstos *ps ); void nastos( struct typstos *ps, struct typdg *pdg ); void zestosu( struct typstos *ps, struct typdg *pdg ); void sortuj( int dane[ ], int N ); void podzial( int dane[ ], int dol, int gora, int *srodek ); void wydruk( int dane[ ], int N );

/* program glowny ------------------------------------------------------ */ void main() // int tab[ ROZMIAR ] = 0,9,2,7,4,5,6,3,8,1,10 ; /* ver.1 */ int tab[ ROZMIAR ] = 25,57,48,37,12,92,86,33 ; /* ver.2 */ int i; sortuj( tab, ROZMIAR ); wydruk( tab, ROZMIAR ); /* Funkcje pomocnicza------------------------------------------------- */ void sortuj( int dane[ ], int N ) int i, j; struct typdg nowedg; // deklaracja zmiennej nowedg typu typdg struct typstos stos; // deklaracja zmiennej stos typu typstos stos.top = -1; nowedg.dol = 0; nowedg.gora = N-1; nastos( &stos, &nowedg ); printf(" " ); for( i=0; i < N; i++) printf(" %2d ", i ); printf("\n"); // nic nie ma na stosie // indeks dolny tablicy do sortowania // indeks górny tablicy do sortowania // zapisz na stos // pomocniczy wydruk

while(!pustystos( &stos ) ) /* powtarzaj, w 1-ej kolejności */ /* podtablice MNIEJSZE */ zestosu( &stos, &nowedg ); /* pobierz ze stosu dół i górę */ while ( nowedg.gora > nowedg.dol ) /* 1-sze tab MNIEJSZE */ printf(" d=%2d g=%2d ", nowedg.dol, nowedg.gora ); wydruk( dane, N ); /* aktualna kolejnosc */ podzial( dane, nowedg.dol, nowedg.gora, &j); printf(" s=%2d\n", j ); /* zwrocony srodek */ if ( j-nowedg.dol > nowedg.gora-j ) /* zapisz na stos dolna WIEKSZA podtablice */ i = nowedg.gora; nowedg.gora = j-1; nastos( &stos, &nowedg ); /* przetwarzaj gorna MNIEJSZA podtablice */ nowedg.dol = j+1; nowedg.gora = i; else /* zapisz na stos gorna WIEKSZA podtablice */ i = nowedg.dol; nowedg.dol = j+1; nastos( &stos, &nowedg ); /* przetwarzaj dolna MIEJSZA podtablice */ nowedg.dol = i; nowedg.gora = j-1; /* end if */ /* end while gora > dol */ /* end while pustystos */ printf(" " ); /* end sortuj */

/* Podzial zbioru ------------------------------------------------------------------ */ /* funkcja przestawia elementy, zwraca indeks srodka = mediany */ /* identyczna jak w programie c4_3a.c */ void podzial( int dane[ ], int dol, int gora, int *srodek ) int a, id, ig, x; a = dane[ dol ]; /* szukamy nowej pozycji tego elementu */ id = dol; /* indeks roboczy dolny */ ig = gora; /* indeks roboczy gorny */ while( id < ig ) while( (dane[ id ] <= a) && (id < gora) ) id++; /* idz do gory */ while( (dane[ ig ] > a) && (ig > dol) ) ig--; /* idz do dolu */ if ( id < ig ) x = dane[ id ]; /* zamien miejscami */ dane[ id ] = dane[ ig ]; /* elementy */ dane[ ig ] = x; /* jesli id < ig */ dane[ dol ] = dane[ ig ]; /* koncowa zamiana */ dane[ ig ] = a; /* dol <--> ig */ *srodek = ig; /* zwroc indeks srodka */

/* OPERACJE NA STOSIE -------------------------------------------- */ int pustystos( struct typstos *ps ) if ( ps->top == -1 ) // zapis: *ps.top = ps->top return( TAK ); else return( NIE ); /* ------------------------------------------------------------------------------ */ void zestosu( struct typstos *ps, struct typdg *pdg ) if ( pustystos(ps) ) printf("stos jest pusty!\n"); exit(1); pdg->dol = ps->granice[ ps->top ].dol; // *ps.granice[ *ps.top ].dol pdg->gora = ps->granice[ ps->top ].gora; // *ps.granice[ *ps.top ].gora (ps->top)--; /* ------------------------------------------------------------------------------ */ void nastos( struct typstos *ps, struct typdg *pdg ) if (ps->top == MAXSTOS-1) printf("blad! Stos jest przepelniony!\n"); exit(1); else (ps->top)++; // (*ps.top)++ ps->granice[ ps->top ].dol = pdg->dol; // jak wyżej ps->granice[ ps->top ].gora = pdg->gora; // jak wyżej

/* OPIS PROGRAMU Jak widać niewykorzystanie funkcji rekurencyjnej bardzo komplikuje algorytm sortowania metodą QuickSort. Po umieszczeniu pierwszego elementu tablicy na poprawnej pozycji, musimy powtórzyć tę samą operację podziału dla dwóch zbiorów elementów: leżących poniżej oraz powyżej niego. Indeks początkowy i końcowy większego zbioru zapisujemy na stosie, a przetwarzamy dalej mniejszy zbiór elementów tablicy. Kiedy warunek: while ( nowedg.gora > nowedg.dol ) nie jest spełniony, zaczynamy zdejmować ze stosu to co zostało tam zapisane, czyli dolne i górne indeksy podtablic, które muszą być jeszcze posortowane: zestosu( &stos, &nowedg ); Funkcja kończy swoje działanie kiedy na stosie już nic nie ma: while(!pustystos( &stos ) ) go Johny, go!. Na początku kładziemy na stosie dolny i górny indeks całej tablicy. stos.top = -1; // nic nie ma na stosie nowedg.dol = 0; // indeks dolny tablicy do sortowania nowedg.gora = N-1; // indeks górny tablicy do sortowania nastos( &stos, &nowedg ); // zapisz na stos Budowę stosu pokazuje poniższy rysunek. Parametr top wskazuje na ostatnią dwuliczbę typu dól/góra zapisaną w tablicy granice[]. top d0 d1 d2 d3 g0 g1 g2 g3 granice[ MAXSTOS ] */ dol gora