Podstawy programowania Część czwarta Tablice koncepcja, deklaracje, podstawowe zastosowania Autor Roman Simiński Kontakt roman.siminski@us.edu.pl www.programowanie.siminskionline.pl Niniejsze opracowanie zawiera skrót treści wykładu, lektura tych materiałów nie zastąpi uważnego w nim uczestnictwa. Opracowanie to jest chronione prawem autorskim. Wykorzystywanie jakiegokolwiek fragmentu w celach innych niż nauka własna jest nielegalne. Dystrybuowanie tego opracowania lub jakiejkolwiek jego części oraz wykorzystywanie zarobkowe bez zgody autora jest zabronione.
Przetwarzanie ciągu liczb Problem Napisać program obliczający sumaryczny, roczny dochód. Program wczytuje dochody z kolejnych 12-stu miesięcy, następnie wyprowadza dochód sumaryczny oraz dochody z kolejnych miesięcy uporządkowane rosnąco. Copyright Roman Simiński Strona : 2
Przetwarzanie ciągu liczb Analiza Właściwie problem nie wydaje się trudny taki program już był omawiany. Wystarczy iteracja while, trzy zmienne..., ale jak uporządkować ciąg liczb, kiedy są one przetwarzane na bieżąco? W danym przebiegu iteracji pamiętany jest tylko dochód z bieżącego miesiąca.?... suma = 0; nr_miesiaca = 1; while( nr_miesiaca <= 12 ) { cout << nr_miesiaca << ": "; cin >> dochod; suma += dochod; ++nr_miesiaca; }... Copyright Roman Simiński Strona : 3
Przetwarzanie ciągu liczb musimy pamiętać wszystkie jego elementy Rozwiązanie siłowe niby działa ale... Dochód z każdego miesiąca przechowywany jest w osobnej zmiennej, w nazwach takich zmiennych występuje numer miesiąca. Obliczenie sumy polega na zsumowaniu wartości 12-stu zmiennych. double dochod1; double dochod2;... double dochod11; double dochod12; cout << 1: ; cin >> dochod1; cout << 2: ; cin >> dochod2;... cout << 12: ; cin >> dochod12; suma = dochod1 + dochod2 +... + dochod11 + dochod12;... Copyright Roman Simiński Strona : 4
Przetwarzanie ciągu liczb musimy pamiętać wszystkie jego elementy Świat programisty 1 2 3 Dochód ze stycznia Dochód z lutego 4 5 6 7 8 9 10 11 12 Dochód z grudnia Zsumuj, posortuj, wyświetl Świat użytkownika Copyright Roman Simiński Strona : 5
Przetwarzanie ciągu liczb niech numeracja startuje od 0-ra Świat programisty Numeracja elementów od wartości 0 0 Dochód ze stycznia 1 2 Dochód z lutego 3 4 5 6 7 8 9 10 11 Dochód z grudnia Zsumuj, posortuj, wyświetl Świat użytkownika Copyright Roman Simiński Strona : 6
Tablice zmienne do przechowywania kolekcji danych tego samego typu Jak zmagazynować wiele liczb i jednocześnie wygodnie nimi manipulować? Zmienna Zmienna składająca składająca się się z z 12-tu 12-tu elementów elementów ( szufladek ). ( szufladek ). Każda Każda z z szufladek szufladek jest jest liczbą liczbą rzeczywistą. rzeczywistą. dochody dochody 1200 1000 1300 500 1500 2000 1200 1800 1000 1400 1500 2300 0 1 2 3 4 5 6 7 8 9 10 11 Każda Każda z z szufladek szufladek posiada posiada swój swój unikatowy unikatowy numer numer od od 0 0 do do 11. 11. Copyright Roman Simiński Strona : 7
Tablice zmienne do przechowywania kolekcji danych tego samego typu Jak zmagazynować wiele liczb i jednocześnie wygodnie nimi manipulować? dochody dochody 1200 1000 1300 500 1500 2000 1200 1800 1000 1400 1500 2300 0 1 2 3 4 5 6 7 8 9 10 11 Taka złożona zmienna, będąca kolekcją ponumerowanych elementów takiego samego typu nazywana jest zmienną tablicą lub w skrócie tablicą. Deklaracja zmiennej będącej tablicą może mieć postać: double dochody[ 12 ]; lub z wykorzystaniem liczby elementów określonej parametrycznie: const int LB_MIESIECY = 12; double dochody[ LB_MIESIECY ]; Copyright Roman Simiński Strona : 8
Tablice zmienne do przechowywania kolekcji danych tego samego typu Deklaracja zmiennej tablicowej jak to czytać? const int LB_MIESIECY = 12; Typ elementów tablicy Typ elementów tablicy Liczba elementów tablicy Liczba elementów tablicy double dochody [ LB_MIESIECY ]; Nazwa zmiennej tablicowej Nazwa zmiennej tablicowej Numery elementów tablicy nazywane są indeksami. Pierwszy element tablicy w językach C/C++ ma zawsze indeks 0, drugi 1, itd.. Dla tablicy liczącej N elementów, indeks ostatniego jej elementu to N 1. Copyright Roman Simiński Strona : 9
Tablice a element tablicy 0 1 2 3 4 5 6 7 8 9 Tablica Tablica Element Element 10 11 dochody [ 1 ] Copyright Roman Simiński Strona : 10
Tablice a różne standardy C i C++ Według standardu C89 i C++03: tablica zawsze składa się z ustalonej, i znanej na etapie kompilacji liczby elementów, liczba elementów tablicy nie ulega zmianie w trakcie działania programu tablice są statyczne. W standardzie C99 istnieją tablice VLA (ang. variable length array): liczba elementów tablicy może być zdefiniowany w trakcie wykonania programu może być określona wartością zmiennej, ta wartość nie musi być znana na etapie kompilacji, liczba elementów tablicy nie ulega zmianie w trakcie działania programu raz stworzona tablica zachowuje swój rozmiar. Copyright Roman Simiński Strona : 11
Parametryzacja rozmiaru tablicy C a C++ #define LB_MIES 12 double dochody[ LB_MIES ]; #define MAKS_DL 80 char bufor[ MAKS_DL ]; C, ANSI89 const int LB_MIES = 12; double dochody[ LB_MIES ]; const int MAKS_DL = 80; char bufor[ MAKS_DL ]; C++ Parametryzacja liczby elementów tablicy pozwala na łatwiejszą modyfikację liczby przetwarzanych elementów. Jest mocno zalecana! Dlaczego? Okaże się już za parę slajdów.... Problemy z const w C dlaczego? Kwalifikator typu const może wystąpić z każdą specyfikacją typu. Zmienna z const powinna być zainicjowana a potem nie może zmieniać wartości. Zmienna z kwalifikatorem const w języku C nie jest traktowana jako wartość stała i nie może być wykorzystywana do określania rozmiaru tablicy. Zmienna z kwalifikatorem const w języku C++ może być wykorzystywana do określania rozmiaru tablicy. Copyright Roman Simiński Strona : 12
Odwoływanie się do elementów tablicy Przypisanie wartości do elementu tablicy Numer elementu tablicy Numer elementu tablicy Krócej: indeks Krócej: indeks dochody[ 0 ] = 0; dochody[ 2 ] = 1000; dochody[ 10 ] = 2000; Nazwa zmiennej tablicowej Nazwa zmiennej tablicowej Krócej: nazwa tablicy Krócej: nazwa tablicy Tablica Tablica Element Element dochody [ 1 ] = 0 Warto Warto ś ś ć ć wstawiana wstawiana do do elementu elementu tablicy tablicy Copyright Roman Simiński Strona : 13
Pojedynczy element tablicy dochody jest jak zwykła zmienna rzeczywista Można przypisywać jej wartości dochody[ 3 ] = 0; Można wstawić do niej wartość wczytaną z klawiatury cout << Podaj dochód styczniowy: ; cin >> dochody[ 0 ]; Można ją wykorzystywać w wyrażeniach dochodbrutto = dochody[ 0 ] * 1.22; Można wyprowadzić jej wartość do strumienia wyjściowego cout << 'Dochód styczniowy wynosi: << dochody[ 0 ]; Copyright Roman Simiński Strona : 14
Dzięki tablicom przetwarzanie ciągów liczbowych jest elastyczniejsze Załóżmy że zadeklarowaną zmienną jest to tzw. zmienna indeksowa int nr_miesiaca; Zerowanie wartości wszystkich dochodów zero do każdego elementu tablicy for( nr_miesiaca = 0; nr_miesiaca < LB_MIESIECY; ++nr_miesiaca ) dochody[ nr_miesiaca ] = 0; Rozwija się w trakcie wykonania programu w: dochody[ 0 ] := 0; dochody[ 1 ] := 0; dochody[ 2 ] := 0; dochody[ 3 ] := 0;... dochody[ 11 ] := 0; Copyright Roman Simiński Strona : 15
Dzięki tablicom przetwarzanie ciągów liczbowych jest elastyczniejsze Zatem jedna iteracja zeruje wszystkie elementy tablicy for( nr_miesiaca = 0; nr_miesiaca < LB_MIESIECY; ++nr_miesiaca ) dochody[ nr_miesiaca ] = 0; Dochody Dochody 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 3 4 5 6 7 8 9 10 11 Zmienna nr_miesiaca Zmienna maszeruje nr_miesiaca maszeruje po po kolejnych kolejnych numerach numerach elementów elementów tablicy: tablicy: 0, 0, 1, 1, 2, 2, 3, 3, 4, 4,...,..., 11. 11. dochody[ nr_miesiaca ] = 0 zeruje dochody[ nr_miesiaca ] = 0 zeruje kolejne kolejne elementy elementy tablicy. tablicy. Copyright Roman Simiński Strona : 16
Dzięki tablicom przetwarzanie ciągów liczbowych jest elastyczniejsze Zatem jedna iteracja zeruje wszystkie elementy tablicy for( nr_miesiaca = 0; nr_miesiaca < LB_MIESIECY; ++nr_miesiaca ) dochody[ nr_miesiaca ] = 0; Dochody Dochody 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 3 4 5 6 7 8 9 10 11 Zmienna nr_miesiaca Zmienna maszeruje nr_miesiaca maszeruje po po kolejnych kolejnych numerach numerach elementów elementów tablicy: tablicy: 0, 0, 1, 1, 2, 2, 3, 3, 4, 4,...,..., 11. 11. dochody[ nr_miesiaca ] = 0 zeruje dochody[ nr_miesiaca ] = 0 zeruje kolejne kolejne elementy elementy tablicy. tablicy. Copyright Roman Simiński Strona : 17
Wypełnienie tablicy danymi wczytanymi ze strumienia wejściowego for( nr_miesiaca = 0; nr_miesiaca < LB_MIESIECY; ++nr_miesiaca ) { cout << nr_miesiaca + 1 << ": "; cin >> dochody[ nr_miesiaca ]; } Rozwija się w trakcie wykonania programu w: cout << 1 << ": "; cin >> dochody[ 0 ]; cout << 2 << ": "; cin >> dochody[ 1 ]; cout << 3 << ": "; cin >> dochody[ 3 ];... cout << 12 << ": "; cin >> dochody[ 11 ]; Copyright Roman Simiński Strona : 18
Wyprowadzenie zawartości tablicy do strumienia wyjściowego for( nr_miesiaca = 0; nr_miesiaca < LB_MIESIECY; ++nr_miesiaca ) cout << endl << nr_miesiaca + 1 << : << dochody[ nr_miesiaca ]; Rozwija się w trakcie wykonania programu w: cout << endl << 1 << : << dochody[ 0 ]; cout << endl << 2 << : << dochody[ 1 ]; cout << endl << 3 << : << dochody[ 2 ];... cout << endl << 12 << : << dochody[ 11 ]; Copyright Roman Simiński Strona : 19
Sumowanie elementów tablicy for( suma = 0, nr_miesiaca = 0; nr_miesiaca < LB_MIESIECY; ++nr_miesiaca ) suma += dochody[ nr_miesiaca ]; Rozwija się w trakcie wykonania programu w: suma += dochody[ 0 ]; suma += dochody[ 1 ]; suma += dochody[ 2 ];... suma += dochody[ 11 ]; Copyright Roman Simiński Strona : 20
Ogólny schemat iteracyjnego przetwarzania tablic for( i = 0; i < LB_ELEM_TABLICY; ++i ) Jaka ś operacja na elemencie i-tym tablicy t: t[ i ] Do iteracyjnego przetwarzania tablic potrzebna jest zmienna indeksowa. Jest to zmienna całkowita, nazwa jest dowolna, najczęściej stosuje się jednak zmienne o nazwach i, j, k, l, m, n,. Najlepiej gdy rozmiar tablicy jest określony nazwaną stałą wtedy łatwiej jest modyfikować rozmiar tablicy bez potencjalnie wielu zmian w programie. Zmienna indeksowa w C++ może być deklarowana w obrębie iteracji for, uwaga wg aktualnego standardu nie jest wtedy dostępna poza iteracją: for( int i = 0; i < LB_ELEM_TABLICY; ++i ) Jaka ś operacja na elemencie i-tym tablicy t: t[ i ] i = 0; // zmienna i nie jest dost ę pna w tym zasi ę gu! Copyright Roman Simiński Strona : 21
Pierwsza przymiarka do programu jeszcze bez porządkowania tablicy #include <iostream> using namespace std; int main() { const int LB_MIESIECY = 12; double dochody[ LB_MIESIECY ]; double suma = 0; int nr_miesiaca; // Krotka informacja o programie cout << "\nobliczam sumaryczny dochod z 12 miesiecy"; cout << "\nwprowadz dochody z kolejnych miesiecy\n"; // Zerowanie elementow tablicy for( nr_miesiaca = 0; nr_miesiaca < LB_MIESIECY; ++nr_miesiaca ) dochody[ nr_miesiaca ] = 0; // Wczytanie danych ze strumienia wejsciowego for( nr_miesiaca = 0; nr_miesiaca < LB_MIESIECY; ++nr_miesiaca ) { cout << nr_miesiaca + 1 << ": "; cin >> dochody[ nr_miesiaca ]; } 1/2 Copyright Roman Simiński Strona : 22
Pierwsza przymiarka do programu jeszcze bez porządkowania tablicy // Sumowanie elementow tablicy for( nr_miesiaca = 0; nr_miesiaca < LB_MIESIECY; ++nr_miesiaca ) suma += dochody[ nr_miesiaca ]; cout << "\nsuma przychodow: " << suma; // Uwaga tutaj brakuje porzadkowania tablicy! // Wyprowadzenie elementow tablicy do strumienia wyjsciowego for( nr_miesiaca = 0; nr_miesiaca < LB_MIESIECY; ++nr_miesiaca ) cout << endl << dochody[ nr_miesiaca ]; cout << endl << "Nacisnij Enter by zakonczyc..." << endl; cin.ignore(); cin.get(); return EXIT_SUCCESS; } 2/2 Copyright Roman Simiński Strona : 23
Uwaga pierwsza optymalizacja // Zerowanie elementow tablicy for( nr_miesiaca = 0; nr_miesiaca < LB_MIESIECY; ++nr_miesiaca ) dochody[ nr_miesiaca ] = 0; // Wczytanie danych ze strumienia wejsciowego for( nr_miesiaca = 0; nr_miesiaca < LB_MIESIECY; ++nr_miesiaca ) { cout << nr_miesiaca + 1 << ": "; cin >> dochody[ nr_miesiaca ]; } W tym przypadku zerowanie tablicy można pominąć. Za chwilę w całości zostanie wypełniona danymi wczytanymi ze strumienia wejściowego programu. Copyright Roman Simiński Strona : 24
Uwaga eliminacja zbędnej iteracji // Wczytanie danych ze strumienia wejsciowego for( nr_miesiaca = 0; nr_miesiaca < LB_MIESIECY; ++nr_miesiaca ) { cout << nr_miesiaca + 1 << ": "; cin >> dochody[ nr_miesiaca ]; } // Sumowanie elementow tablicy for( nr_miesiaca = 0; nr_miesiaca < LB_MIESIECY; ++nr_miesiaca ) suma += dochody[ nr_miesiaca ]; // Wczytanie danych ze strumienia wejsciowego for( nr_miesiaca = 0; nr_miesiaca < LB_MIESIECY; ++nr_miesiaca ) { cout << nr_miesiaca + 1 << ": "; cin >> dochody[ nr_miesiaca ]; } suma += dochody[ nr_miesiaca ]; Copyright Roman Simiński Strona : 25
Jak uporządkować tablicę dochodów? dochody dochody 1200 1000 1300 500 1500 2000 1200 1800 1000 1400 1500 2300 0 1 2 3 4 5 6 7 8 9 10 11 Jak to ułożyć te liczby w kolejności rosnącej? dochody dochody 500 1000 1000 1200 1200 1300 1400 1500 1500 1800 2000 2300 0 1 2 3 4 5 6 7 8 9 10 11 Copyright Roman Simiński Strona : 26
Jak uporządkować tablicę dochodów sortowanie Zagadnienie porządkowania elementów tablicy wg pewnego kryterium nazywa się sortowaniem. Istnieje wiele metod sortowania zawartości tablic przyjmują postać algorytmów sortowania dobrze opisanych w literaturze związanej z programowaniem i algorytmiką. Biblia algorytmów sortowania to książka N. Wirtha: Algorytmy + struktury danych = programy Istnieją proste i intuicyjnie zrozumiałe algorytmy sortowania te nie są zwykle efektywne. Efektywne algorytmy sortowania stosują sprytne choć nie od razu zrozumiałe rozwiązania. Do sortowania niewielkich tablic wystarczą proste algorytmy sortowania nie strzelamy a armaty do wróbelka :) Copyright Roman Simiński Strona : 27
Sortowanie przez wybieranie koncepcja Wśród nieuporządkowanych elementów będziemy wyszukiwać najmniejszy i odkładać go do puli uporządkowanych. nieuporządkowane 8 1 5 9 6 4 Copyright Roman Simiński Strona : 28
Sortowanie przez wybieranie koncepcja Wybieramy element minimalny nieuporządkowane 8 1 5 9 6 4 Copyright Roman Simiński Strona : 29
Sortowanie przez wybieranie koncepcja Przenosimy do zbioru elementów uporządkowanych nieuporządkowane 8 1 5 9 6 4 uporządkowane 1 Copyright Roman Simiński Strona : 30
Sortowanie przez wybieranie koncepcja Z pozostałych, nieuporządkowanych elementów wybieramy minimalny nieuporządkowane 8 1 5 9 6 4 uporządkowane 1 Copyright Roman Simiński Strona : 31
Sortowanie przez wybieranie koncepcja Przenosimy do zbioru elementów uporządkowanych nieuporządkowane 8 1 5 9 6 4 uporządkowane 1 4 Copyright Roman Simiński Strona : 32
Sortowanie przez wybieranie koncepcja Z pozostałych, nieuporządkowanych elementów wybieramy minimalny nieuporządkowane 8 1 5 9 6 4 1 4 uporządkowane Copyright Roman Simiński Strona : 33
Sortowanie przez wybieranie koncepcja Przenosimy do zbioru elementów uporządkowanych nieuporządkowane 8 1 5 9 6 4 1 4 uporządkowane 5 Copyright Roman Simiński Strona : 34
Sortowanie przez wybieranie koncepcja Z pozostałych, nieuporządkowanych elementów wybieramy minimalny nieuporządkowane 8 1 5 9 6 4 1 4 5 uporządkowane Copyright Roman Simiński Strona : 35
Sortowanie przez wybieranie koncepcja Przenosimy do zbioru elementów uporządkowanych nieuporządkowane 8 1 5 9 6 4 1 4 5 uporządkowane 6 Copyright Roman Simiński Strona : 36
Sortowanie przez wybieranie koncepcja Z pozostałych, nieuporządkowanych elementów wybieramy minimalny nieuporządkowane 8 1 5 9 6 4 1 4 5 6 uporządkowane Copyright Roman Simiński Strona : 37
Sortowanie przez wybieranie koncepcja Przenosimy do zbioru elementów uporządkowanych nieuporządkowane 8 1 5 9 6 4 1 4 5 6 8 uporządkowane Copyright Roman Simiński Strona : 38
Sortowanie przez wybieranie koncepcja Z pozostałych, nieuporządkowanych elementów wybieramy minimalny nieuporządkowane 8 1 5 9 6 4 1 4 5 6 8 uporządkowane Copyright Roman Simiński Strona : 39
Sortowanie przez wybieranie koncepcja Przenosimy do zbioru elementów uporządkowanych nieuporządkowane 8 1 5 9 6 4 1 4 5 6 8 9 uporządkowane Copyright Roman Simiński Strona : 40
Sortowanie przez wybieranie koncepcja nieuporządkowane 8 1 5 9 6 4 Dwa zbiory, dwie półki na elementy... 1 4 5 6 8 9 uporządkowane Copyright Roman Simiński Strona : 41
Sortowanie przez wybieranie koncepcja nieuporządkowane 8 1 5 9 6 4 A może użyć tylko jednej półki? 1 4 5 6 8 9 uporządkowane Copyright Roman Simiński Strona : 42
Sortowanie przez wybieranie tylko jedna półka 8 1 5 9 6 4 uporządkowane nieuporządkowane Copyright Roman Simiński Strona : 43
Sortowanie przez wybieranie tylko jedna półka Wybieramy element minimalny... 8 1 5 9 6 4 uporządkowane nieuporządkowane Copyright Roman Simiński Strona : 44
Sortowanie przez wybieranie tylko jedna półka... i przenosimy na początek części nieuporządkowanej... 1 8 5 9 6 4 uporządkowane nieuporządkowane Copyright Roman Simiński Strona : 45
Sortowanie przez wybieranie tylko jedna półka ale co zrobić z elementem, który jest na początku? 1 8 5 9 6 4 uporządkowane nieuporządkowane Copyright Roman Simiński Strona : 46
Sortowanie przez wybieranie tylko jedna półka A może po prostu zamienić ze sobą elementy...? 1 5 9 6 4 8 uporządkowane nieuporządkowane Copyright Roman Simiński Strona : 47
Sortowanie przez wybieranie tylko jedna półka A może po prostu zamienić ze sobą elementy...? 1 8 5 9 6 4 uporządkowane nieuporządkowane Copyright Roman Simiński Strona : 48
Sortowanie przez wybieranie tylko jedna półka Teraz najmniejszy element jest na swoim miejscu. On jest już uporządkowany. 1 8 5 9 6 4 uporządkowane nieuporządkowane Copyright Roman Simiński Strona : 49
Sortowanie przez wybieranie tylko jedna półka Z pozostałych, nieuporządkowanych elementów wybieramy minimalny. 1 8 5 9 6 4 uporządkowane nieuporządkowane Copyright Roman Simiński Strona : 50
Sortowanie przez wybieranie tylko jedna półka Przenosimy na początek części nieuporządkowanej. 1 8 5 9 6 4 uporządkowane nieuporządkowane Copyright Roman Simiński Strona : 51
Sortowanie przez wybieranie tylko jedna półka Teraz znaleziony element jest na swoim miejscu. Rozrasta się część uporządkowana. 1 4 5 9 6 8 uporządkowane nieuporządkowane Copyright Roman Simiński Strona : 52
Sortowanie przez wybieranie tylko jedna półka Z pozostałych, nieuporządkowanych elementów wybieramy minimalny. W tym przypadku jest on akurat na swoim miejscu. 1 4 5 9 6 8 uporządkowane nieuporządkowane Copyright Roman Simiński Strona : 53
Sortowanie przez wybieranie tylko jedna półka Teraz znaleziony element jest na swoim miejscu. Rozrasta się część uporządkowana. 1 4 5 9 6 8 uporządkowane nieuporządkowane Copyright Roman Simiński Strona : 54
Sortowanie przez wybieranie tylko jedna półka Z pozostałych, nieuporządkowanych elementów wybieramy minimalny. 1 4 5 9 6 8 uporządkowane nieuporządkowane Copyright Roman Simiński Strona : 55
Sortowanie przez wybieranie tylko jedna półka Przenosimy na początek części nieuporządkowanej. 1 4 5 9 6 8 uporządkowane nieuporządkowane Copyright Roman Simiński Strona : 56
Sortowanie przez wybieranie tylko jedna półka Teraz znaleziony element jest na swoim miejscu. Rozrasta się część uporządkowana. 1 4 5 6 9 8 uporządkowane nieuporządkowane Copyright Roman Simiński Strona : 57
Sortowanie przez wybieranie tylko jedna półka Z pozostałych, nieuporządkowanych elementów wybieramy minimalny. 1 4 5 6 9 8 uporządkowane nieuporządkowane Copyright Roman Simiński Strona : 58
Sortowanie przez wybieranie tylko jedna półka Przenosimy na początek części nieuporządkowanej. 1 4 5 6 9 8 uporządkowane nieuporządkowane Copyright Roman Simiński Strona : 59
Sortowanie przez wybieranie tylko jedna półka Wszystkie elementy za wyjątkiem ostatniego są uporządkowane... to znaczy, że i ostatni jest na swoim miejscu. 1 4 5 6 8 9 uporządkowane nieuporządkowane Copyright Roman Simiński Strona : 60
Zanim posortujemy wyszukiwanie minimum, przypomnienie double minimalny; // Minimalny int nr_minimalnego; // Indeks minimalnego elementu Ustal początkową wartość elementu minimalnego: minimalny = dochody[ 0 ] Ustal początkowy numer elementu minimalnego: nr_minimalnego = 0 // Sprawd ź kolejne elementy, wymie ń minimum gdy trzeba Dla każdego elementu tablicy począwszy od drugiego if( aktualny odwiedzony < minimalny ) { minimalny = aktualny odwiedzony; nr_minimalnego = numer aktualnie odwiedzonego; } Copyright Roman Simiński Strona : 61
Zanim posortujemy wyszukiwanie minimum, przypomnienie double minimalny; // Minimalny int nr_minimalnego; // Indeks minimalnego elementu // Ustalenie wartosci poczatkowych dla elementu minimalnego minimalny = dochody[ 0 ]; nr_minimalnego = 0; // Sprawdz kazdy nast ę pny i zapamietaj indeks i wartosc gdy mniejszy for( int i = 1; i < LB_MIESIECY; i++ ) if( dochody[ i ] < minimalny ) { minimalny = dochody[ i ]; nr_minimalnego = i; } Copyright Roman Simiński Strona : 62
Sortowanie krok pierwszy double minimalny; // Minimalny int nr_minimalnego; // Indeks minimalnego elementu // Ustalenie wartosci poczatkowych dla elementu minimalnego minimalny = dochody[? ]; nr_minimalnego =? ; // Sprawdz kazdy nast ę pny i zapamietaj indeks i wartosc gdy mniejszy for( int i = 1; i < LB_MIESIECY; i++ ) if( dochody[ i ] < minimalny ) { minimalny = dochody[ i ]; nr_minimalnego = i; } Sortowanie polega na wyznaczaniu minimum spośród jeszcze nieposortowanych. Początek części nieposortowanej się zmienia... Copyright Roman Simiński Strona : 63
Sortowanie krok pierwszy double minimalny; // Minimalny wsrod nieposortowanych int nr_minimalnego; // Indeks minimalnego elementu int do_posortowania; // Indeks poczatku czesci nieposortowanej for( do_posortowania = 0; do_posortowania < LB_MIESIECY-1; ++do_posortowania ) { Znajdź minimum wśród elementów od do_posortowania do końca tablicy } // Zamieniamy minimalny z pierwszym nieposortowanym dochody[ nr_minimalnego ] = dochody[ do_posortowania ]; dochody[ do_posortowania ] = minimalny; Copyright Roman Simiński Strona : 64
Sortowanie krok pierwszy double minimalny; // Minimalny wsrod nieposortowanych int nr_minimalnego; // Indeks minimalnego elementu int do_posortowania; // Indeks poczatku czesci nieposortowanej for( do_posortowania = 0; do_posortowania < LB_MIESIECY-1; ++do_posortowania ) { // Poczatkowe minimum -- pierwszy nieposortowany minimalny = dochody[ do_posortowania ]; nr_minimalnego = do_posortowania; // Sprawdz kazdy nast ę pny i zapamietaj indeks i wartosc gdy mniejszy for( int i = do_posortowania + 1; i < LB_MIESIECY; i++ ) if( dochody[ i ] < minimalny ) { minimalny = dochody[ i ]; nr_minimalnego = i; } } // Przepisujemy pierwszy nieposortowany w miejsce minimum dochody[ nr_minimalnego ] = dochody[ do_posortowania ]; dochody[ do_posortowania ] = minimalny; Ten fragment wstawiamy do programu ze str. 22-23 w miejsce czerwonego komentarza Copyright Roman Simiński Strona : 65
Suplement kompresja iteracji Poniższa iteracja: for( nr_miesiaca = 0; nr_miesiaca < LB_MIESIECY; ++nr_miesiaca ) dochody[ nr_miesiaca ] = 0; może być zapisana w krótszej postaci: for( nr_miesiaca = 0; nr_miesiaca < LB_MIESIECY; dochody[ nr_miesiaca++ ] = 0 ) ; Dlaczego? Copyright Roman Simiński Strona : 66
Suplement kompresja iteracji Wersja przedrostkowa zwiększa (zmniejsza) wartość argumentu przed użyciem jego wartości. Wersja przyrostkowa zwiększa (zmniejsza) wartość argumentu po użyciem jego wartości. int a = 5, b; b = ++a; a == 6, b == 6 int a = 5, b; b = a++; a == 6, b == 5 int licznik = 0; cout << Licznik: << licznik; licznik++;... licznik++; cout << Licznik: << licznik; int licznik = 0; cout << Licznik: << licznik++;... cout << Licznik: << ++licznik; Copyright Roman Simiński Strona : 67
Suplement kompresja iteracji Uwaga! Średnika nie można pominąć oznacza on instrukcję pustą. for( nr_miesiaca = 0; nr_miesiaca < LB_MIESIECY; dochody[ nr_miesiaca++ ] = 0 ) ; Inny przykład: for( nr_miesiaca = 0; nr_miesiaca < LB_MIESIECY; nr_miesiaca++ ) suma += dochody[ nr_miesiaca ]; for( nr_miesiaca = 0; nr_miesiaca < LB_MIESIECY; suma += dochody[ nr_miesiaca++ ] ) ; Copyright Roman Simiński Strona : 68
Suplement kompresja iteracji Gdy kolejność wykonywania operacji na tablicy nie ma znaczenia, np. iteracja while: nr_miesiaca = LB_MIESIECY; while( --nr_miesiaca >= 0 ) dochody[ nr_miesiaca ] = 0; lub z wykorzystaniem iteracji for: for( nr_miesiaca = LB_MIESIECY; --nr_miesiaca>=0 ; tab[ nr_miesiaca ] = 0 ) ; Copyright Roman Simiński Strona : 69
Problem do rozwiązania statystyka czasów przejazdu slalomu Napisać program rejestrujący czasy przejazdu zawodników startujących w slalomie. Wymagania dla programu: Liczba zawodników zwykle 30. Wpisywanie danych na bieżąco, wyniki po wpisaniu wszystkich czasów. Wyświetlenie czasów uporządkowanych rosnąco od najlepszego do najgorszego. Wyznaczenie i wyświetlenie statystyki czasów: czasu średniego, wartości środkowej (mediany), wariancji i odchylenia standardowego. Copyright Roman Simiński Strona : 70
Analiza problemu co mamy na wejściu? Na wejściu mamy 30-ci liczb rzeczywistych każdy z nich to czas przejazdu odpowiedniego zawodnika. 1 2 3 30 14.5 14.8 13.5 16 1 2 30 3 Copyright Roman Simiński Strona : 71
Analiza problemu jak zapamiętać dane wejściowe? Czasy przejazdów 30 zawodników startujących w slalomie można zapamiętać w 30-to elementowej tablicy. // Liczba zawodnikow const int LB_ZAWOD = 30; // Tablica do przechowywania czasow double czasy[ LB_ZAWOD ]; 0 1 2 29 1 14.5 14.8 13.5 16 2 30 3 Copyright Roman Simiński Strona : 72
Analiza problemu czasy należy uporządkować narastająco Wystarczy wykorzystać dowolny z algorytmów sortowania dla 30 elementów może to być jakikolwiek z prostych algorytmów sortowania. Dane wejściowe 0 1 2 29 14.5 14.8 13.5 16 Sortowanie Dane uporządkowane 0 1 2 29 13.5 14.5 14.8 16 Uwaga! Aby można było posortować dane, trzeba je po wczytaniu zmagazynować w pamięci operacyjne najlepiej w tablicy. Algorytmów sortowania tablic jest wiele. Copyright Roman Simiński Strona : 73
Analiza problemu statystyka czasów, średnia i mediana Czasy tworzą ciąg 30-stu danych liczbowych. Załóżmy, że tych liczb jest n. Możemy wtedy powiedzieć, że mamy n danych liczbowych a 1, a 2, a 3,..., a n. Średnia arytmetyczna a śr to: a śr = a 1 + a 2 + a 3 + + a n n Mediana uporządkowanego rosnąco ciągu n liczb a 1 a 2 a 3 a n : to środkowy wyraz ciągu (dla n nieparzystego), to średnia arytmetyczna środkowych wyrazów ciągu (dla n parzystego). Copyright Roman Simiński Strona : 74
Analiza problemu statystyka czasów, wariancja i odchylenie Wariancja n danych liczbowych a 1, a 2, a 3,..., a n o średniej arytmetycznej a śr to: σ 2 = (a 1 a śr ) 2 + (a 2 a śr ) 2 + (a 3 a śr ) 2 + ( a n a śr ) 2 n Odchylenie standardowe σ to pierwiastek kwadratowy z wariancji: σ = σ 2 Copyright Roman Simiński Strona : 75
Analiza problemu statystyka czasów, po co to wszystko? Wartość średniej arytmetycznej nie zawsze dobrze opisuje zbiór danych dane odstające mocno zaburzają wartość średniej. Mediana może lepiej przybliżać informację o typowych czasach przejazdów uzyskiwanych przez większość zawodników. Przykład: Czasy przejazdów: 1 2 2 3 3 3 3 4 30 40 a śr = 9.1 mediana = 3 Copyright Roman Simiński Strona : 76
Analiza problemu statystyka czasów, po co to wszystko? Wariancja i odchylenie standardowe powie jak czasy przejazdów są rozrzucone wokół czasu średniego. Mniejsza wartość odchylenia standardowego oznacza, że więcej czasów przejazdów jest blisko średniej. Większa wartość odchylenia standardowego oznacza, że rozkład czasów jest bardziej równomierny jest więcej czasów bliskich wartości skrajnych. Przykład: Czasy przejazdów: 1 2 2 3 3 3 3 4 4 5 a śr = 3 σ 1.1 Czasy przejazdów: 1 1 1 2 3 3 4 5 5 5 a śr = 3 σ 1.6 Copyright Roman Simiński Strona : 77
Czas na program, wersja najprostsza #include <cstdlib> #include <cmath> #include <iostream> using namespace std; int main() { const int LB_ZAWOD = 30; double czasy[ LB_ZAWOD ]; // Liczba zawodnikow // Tablica do przechowywania czasow double suma, srednia, mediana; // Zmienne dla statystyki czasow double wariancja, odchylenie; int nr_min, roboczy; // Zmienne dla algorytmu sortowania double min; int i; // Zmienna robocza iteracji // Wprowadzenie wartosci poszczegolnych czasow i zapisanie w tablicy cout << "Podaj czasy przejazdow kolejnych zawodnikow:" << endl; for( i = 0; i < LB_ZAWOD; i++ ) { cout << i + 1 << ": "; cin >> czasy[ i ]; 1/4 } Copyright Roman Simiński Strona : 78
Czas na program, wersja najprostsza // Wyznaczenie wartosci sredniej wprowadzonych czasow for( i = 0, suma = 0; i < LB_ZAWOD; suma += czasy[ i++ ] ) ; // Sortowanie przez proste wybieranie for( roboczy = 0; roboczy < LB_ZAWOD - 1; roboczy++ ) { // Ustalamy robocze minimum min = czasy[ roboczy ]; nr_min = roboczy; // Czy wsrod kolejnych elementow jest mniejszy? for( i = roboczy + 1; i < LB_ZAWOD; i++ ) if( czasy[ i ] < min ) { min = czasy[ i ]; // Zapamietaj mniejszy nr_min = i; // Zapamietaj nr mniejszego } } // Zamien mniejszy z roboczym czasy[ nr_min ] = czasy[ roboczy ]; czasy[ roboczy ] = min; 2/4 Copyright Roman Simiński Strona : 79
Czas na program, wersja najprostsza // Wyznaczenie sredniej i mediany srednia = suma / LB_ZAWOD; if( LB_ZAWOD % 2!= 0 ) mediana = czasy[ LB_ZAWOD / 2 ]; // Liczba czasów jest nieparzysta else mediana = ( czasy[ LB_ZAWOD / 2-1 ] + czasy[ LB_ZAWOD / 2 ] ) / 2; // Wyznaczanie wariancji i odchylenia standartowego. Ponownie // wykorzystujemy zmienna suma -- teraz do wyznaczenia sumy kwadratów // roznic od wartosci sredniej for( i = 0, suma = 0; i < LB_ZAWOD; i++ ) suma += pow( czasy[ i ] - srednia, 2 ); // Podnies do drugiej potegi wariancja = suma / LB_ZAWOD; odchylenie = sqrt( wariancja ); // Wyprowadzenie zawartosci tablicy do strumienia wyjsciowego cout << "\nczasy uporzadkowane rosnaco:"; for( i = 0; i < LB_ZAWOD; i++ ) cout << endl << czasy[ i ]; 3/4 Copyright Roman Simiński Strona : 80
Czas na program, wersja najprostsza cout << fixed; // Notacja z kropka dziesietna cout.precision( 2 ); // Dwa miejsca po przecinku cout << "\nstatystyka czasow przejazdow"; cout << "\n Srednia: " << srednia; cout << "\n Srodkowa: " << mediana; cout << "\n Wariancja: " << wariancja; cout << "\nodchylenie: " << odchylenie; } cout << endl << "Nacisnij Enter by zakonczyc program"; cin.ignore(); cin.get(); return EXIT_SUCCESS; 4/4 Copyright Roman Simiński Strona : 81
Suplement kopiowanie tablic const int LB_ZAWOD = 30; // Liczba zawodnikow double czasy[ LB_ZAWOD ]; // Tablica do przechowywania czasow double czasy_org[ LB_ZAWOD ]; // Tablica z oryginalami czasow... Zapisz kopie danych z tablicy czasy w tablicy czasy_org... Wykonaj sortowanie... Wyprowadź dane posortowane... czasy 1 2 3 30 14.5 14.8 13.5 16 czasy_org 14.5 14.8 13.5 16 1 2 3 30 Copyright Roman Simiński Strona : 82
Suplement kopiowanie tablic Tak w języku C i C++ nie wolno: czasy_org = czasy; // Nie wolno przypisywać do siebie tablic Trzeba przepisać wartości każdego z elementów: for(i = 0; i < LB_ZAWOD; i++ ) czasy_org[ i ] = czasy[ i ]; czasy 1 2 3 30 14.5 14.8 13.5 16 czasy_org 14.5 14.8 13.5 16 1 2 3 30 Copyright Roman Simiński Strona : 83
Wyniki pięcioboju, wskazanie zwycięzcy w parze zawodników W pewnym pięcioboju zwodnicy rywalizują ze sobą parami. Punkty zdobyte w czasie każdej z pięciu konkurencji są sumowane. Zwycięża ten zawodnik, który zgromadził większą liczbę punktów. Należy napisać program, pozwalający na wczytanie punktów zgromadzonych przez każdego zawodnika, w każdej z pięciu konkurencji. Zadaniem programu jest wyznaczenie sumy punktów i wytypowanie zwycięzcy. Punkty 1-go zawodnika 3 5 4 3 5 Suma pkt. 1-go zawodnika 20 Wygrywa drugi Punkty 2-go zawodnika 4 5 4 4 5? Suma pkt. 2-go zawodnika 22 Copyright Roman Simiński Strona : 84
Tablica jak magazyn dla punktów każdej z konkurencji Suma pkt. 1-go zawodnika const int LB_KONK = 5; int punkty1[ LB_KONK ]; int suma1; 20 3 5 4 3 5 0 1 2 3 4 Punkty 1-go zawodnika Punkty 2-go zawodnika 0 1 2 3 4? Wygrywa drugi const int LB_KONK = 5; int punkty2[ LB_KONK ]; int suma2; 4 5 4 4 5 22 Suma pkt. 2-go zawodnika Copyright Roman Simiński Strona : 85
Przykładowe rozwiązanie, wersja pierwsza #include <cstdlib> #include <iostream> using namespace std; int main() { const int LB_KONK = 5; // Liczba konkurencji int punkty1[ LB_KONK ]; // Punkty 1-go zawodnika int punkty2[ LB_KONK ]; // Punkty 2-go zawodnika int i, suma1, suma2; // Czytaj punkty zawodnikow cout << "Podaj punkty pierwszego zawodnika:" << endl; for( i = 0; i < LB_KONK; i++ ) { cout << ">"; cin >> punkty1[ i ]; } cout << "Podaj punkty drugiego zawodnika:" << endl; for( i = 0; i < LB_KONK; i++ ) { cout << ">"; cin >> punkty2[ i ]; } 1/2 Copyright Roman Simiński Strona : 86
Przykładowe rozwiązanie, wersja pierwsza // Sumuj punkty zawodnikow for( i = 0, suma1 = 0; i < LB_KONK; suma1 += punkty1[ i++ ] ) ; for( i = 0, suma2 = 0; i < LB_KONK; suma2 += punkty2[ i++ ] ) ; cout << endl << "Suma punktow pierwszego zawodnika: " << suma1; cout << endl << "Suma punktow drugiego zawodnika: " << suma2; // Wytypuj zwyciezce if( suma1 > suma2 ) cout << endl << "Wygral pierwszy zawodnik"; else if( suma1 < suma2 ) cout << endl << "Wygral drugi zawodnik"; else cout << endl << "Remis"; cout << endl << "Nacisnij Enter by zakonczyc program"; cin.ignore(); cin.get(); return EXIT_SUCCESS; } 2/2 Copyright Roman Simiński Strona : 87
Przykładowe rozwiązanie, wersja pierwsza poprawki, cd....... for( i = 0, suma1 = 0; i < LB_KONK; suma1 += punkty1[ i++ ] ) ; for( i = 0, suma2 = 0; i < LB_KONK; suma2 += punkty2[ i++ ] ) ; cout << endl << "Suma punktow pierwszego zawodnika: " << suma1; cout << endl << "Suma punktow drugiego zawodnika: " << suma2;... Sumowanie, zamiast dwóch iteracji jedna:... for( i = 0, suma1 = 0, suma2 = 0; i < LB_KONK; i++ ) { suma1 += punkty1[ i ]; suma2 += punkty2[ i ]; } cout << endl << "Suma punktow pierwszego zawodnika: " << suma1; cout << endl << "Suma punktow drugiego zawodnika: " << suma2;... Copyright Roman Simiński Strona : 88
Idziemy o krok dalej. A co, gdy zawodników jest np. 10-ciu? const int LB_KONK = 5; int punkty1[ LB_KONK ]; int suma1; int punkty2[ LB_KONK ]; int suma2; Punkty 1-go zawodnika 3 5 4 3 5 0 1 2 3 4 Punkty 2-go zawodnika 4 3 4 3 5 0 1 2 3 4 Tyle tablic...? int punkty3[ MAKS LB_KONK ]; ]; int suma3;... int punkty10[ LB_KONK ]; int suma10; Punkty 3-go zawodnika 36 5 45 36 5 0 1 2 3 4 Punkty 10-go zawodnika 1 4 4 3 2 0 1 2 3 4? Wygrywa nr 3 Copyright Roman Simiński Strona : 89
Idziemy o krok dalej. A co, gdy zawodników jest np. 10-ciu? A może by te tablice zapisać w tablicy?! Punkty 1-go zawodnika 3 5 4 3 5 0 1 2 3 4 Punkty 2-go zawodnika 4 3 4 3 5 0 1 2 3 4 Punkty 3-go zawodnika 36 5 45 36 5 0 1 2 3 4... Punkty 10-go zawodnika 1 4 4 3 2 0 1 2 3 4 0 1 2 3 4 3 5 4 3 5 4 3 4 3 5 36 5 45 36 5..... 1 4 4 3 2 0 1 2... 9 Copyright Roman Simiński Strona : 90
Koncepcja tablicy dwuwymiarowej Stałe określające liczbę zawodników oraz konkurencji: const int LB_ZAWOD = 10; // Liczba zawodnikow const int LB_KONK = 5; // Liczba konkurencji Tablica dwuwymiarowa to inaczej tablica, której elementami są tablice: int punkty[ LB_ZAWOD ][ LB_KONK ]; Punkty 1-go zawodnika 0 Punkty 2-go zawodnika 1 Punkty 3-go zawodnika 2...... Punkty 10-go zawodnika 9 0 1 2 3 4 3 5 4 3 5 4 3 4 3 5 36 5 45 36 5..... 1 4 4 3 2 Tablicy dwuwymiarowej odpowiada matematyczne pojęcie macierzy. Tablicy jednowymiarowej odpowiada wektor. Copyright Roman Simiński Strona : 91
Prosta tablica dwuwymiarowa deklaracja Stałe określające liczbę wierszy i kolumn: const int LB_W = 3; // Liczba wierszy const int LB_K = 4; // Liczba liczba kolumn Tablica dwuwymiarowa o rozmiarze 3x4 (LB_WxLB_K): int tablica[ LB_W ][ LB_K ]; 0 1 2 3 Wiersz 1 0 Wiersz 2 1 Wiersz 3 2 3 5 4 3 Kolumna 1 Kolumna 2 Kolumna 3 Kolumna 4 Copyright Roman Simiński Strona : 92
Prosta tablica dwuwymiarowa przykłady operacji Wstawianie liczby 0 do wszystkich elementów pierwszego wiersza: const int LB_W = 3; // Liczba wierszy const int LB_K = 4; // Liczba liczba kolumn int tablica[ LB_W ][ LB_K ]; int w, k; // Roboczy numer wiersza i kolumny for( k = 0; k < LB_K; k++ ) tablica[ 0 ][ k ] = 0; 0 1 2 0 1 2 3 0 0 0 0 3 5 4 3 Copyright Roman Simiński Strona : 93
Prosta tablica dwuwymiarowa przykłady operacji Wstawianie liczby 0 do wszystkich elementów pierwszej kolumny: const int LB_W = 3; // Liczba wierszy const int LB_K = 4; // Liczba liczba kolumn int tablica[ LB_W ][ LB_K ]; int w, k; // Roboczy numer wiersza i kolumny for( w = 0; w < LB_W; w++ ) tablica[ w ][ 0 ] = 0; 0 1 2 0 1 2 3 0 0 30 5 4 3 Copyright Roman Simiński Strona : 94
Prosta tablica dwuwymiarowa przykłady operacji Wstawianie liczby 0 do wszystkich elementów tablicy (wypełnianie wierszami): const int LB_W = 3; // Liczba wierszy const int LB_K = 4; // Liczba liczba kolumn int tablica[ LB_W ][ LB_K ]; int w, k; // Roboczy numer wiersza i kolumny for( w = 0; w < LB_W; w++ ) for( k = 0; k < LB_K; k++ ) tablica[ w ][ k ] = 0; 0 1 2 0 1 2 3 0 0 0 0 0 0 0 0 30 50 40 30 Przy każdym wykonaniu iteracji wewnętrznej, nr wiersza w jest ustalony. Zmienia się dopiero po wypełnieniu wartością 0 całego wiersza. Copyright Roman Simiński Strona : 95
Prosta tablica dwuwymiarowa przykłady operacji Sumowanie wartości elementów w każdym wierszu const int LB_W = 3; // Liczba wierszy const int LB_K = 4; // Liczba liczba kolumn int tablica[ LB_W ][ LB_K ]; int w, k; // Roboczy numer wiersza i kolumny for( w = 0; w < LB_W; w++ ) { int suma = 0; for( k = 0; k < LB_K; k++ ) suma += tablica[ w ][ k ]; cout << endl << suma; } 0 1 2 0 1 2 3 1 1 2 2 2 2 1 0 31 50 41 30 6 5 2 Copyright Roman Simiński Strona : 96
Prosta tablica dwuwymiarowa przykłady operacji Wprowadzanie danych do tablicy z cin wierszami. const int LB_W = 3; // Liczba wierszy const int LB_K = 4; // Liczba liczba kolumn int tablica[ LB_W ][ LB_K ]; int w, k; // Roboczy numer wiersza i kolumny for( w = 0; w < LB_W; w++ ) { for( k = 0; k < LB_K; k++ ) { cout << endl << '>'; cin >> tablica[ w ][ k ]; } } 0 1 2 0 1 2 3 1 2 3 3 5 4 3 >1 >2 >3 >_ Copyright Roman Simiński Strona : 97
Prosta tablica dwuwymiarowa przykłady operacji Wyprowadzanie danych z tablicy do cout wierszami. const int LB_W = 3; // Liczba wierszy const int LB_K = 4; // Liczba liczba kolumn int tablica[ LB_W ][ LB_K ]; int w, k; // Roboczy numer wiersza i kolumny for( w = 0; w < LB_W; w++ ) { cout << endl; for( k = 0; k < LB_K; k++ ) cout << tablica[ w ][ k ] << ' '; } 0 1 2 0 1 2 3 1 2 3 4 2 3 4 5 3 54 45 63 1 2 3 4 2 3 4 5 3 4 5 6 Copyright Roman Simiński Strona : 98
Wracamy do programu z wynikami 10-ciu zawodników Stałe określające liczbę zawodników oraz konkurencji, zmienne programu: const int LB_ZAWOD = 10; // Liczba zawodnikow const int LB_KONK = 5; // Liczba konkurencji int punkty[ LB_ZAWOD ][ LB_KONK ]; // Tablica punktów int nr_zawod, nr_konk; int maks, nr_maks; // Zmienne robocze iteracji // Minimum i nr minimum Punkty 1-go zawodnika 0 Punkty 2-go zawodnika 1 Punkty 3-go zawodnika 2...... Punkty 10-go zawodnika 9 0 1 2 3 4 3 5 4 3 5 4 3 4 3 5 36 5 45 36 5..... 1 4 4 3 2 Copyright Roman Simiński Strona : 99
Tablica wyników a suma punktów zawodnika Będziemy wyznaczać sumy punktów każdego z zawodników. Sum zatem będzie tyle ile zawodników, gdzie je zapamiętać? Punkty 1-go zawodnika 0 Punkty 2-go zawodnika 1 Punkty 3-go zawodnika 2...... Punkty 10-go zawodnika 9 0 1 2 3 4 3 5 4 3 5 4 3 4 3 5 36 5 45 36 5..... 1 4 4 3 2 20 19 27 5. 14 Potrzebna kolejna tablica? Copyright Roman Simiński Strona : 100
Tablica wyników a suma punktów zawodnika Wprowadzamy dodatkową kolumnę w tablicy, będzie ona przechowywać sumę punktów każdego zawodnika: Punkty 1-go zawodnika 0 Punkty 2-go zawodnika 1 Punkty 3-go zawodnika 2...... Punkty 10-go zawodnika 9 0 1 2 3 4 3 5 4 3 5 4 3 4 3 5 36 5 45 36 5..... 1 4 4 3 2 5 20 19 27 5. 14 const int LB_ZAWOD = 10; // Liczba zawodnikow const int LB_KONK = 5; // Liczba konkurencji const int SUMA = LB_KONK; // Indeks elemementu wiersza na sume punktow int punkty[ LB_ZAWOD ][ LB_KONK + 1 ]; // Tablica punktów int nr_zawod, nr_konk; int maks, nr_maks; // Zmienne robocze iteracji // Minimum i nr minimum Copyright Roman Simiński Strona : 101
Odczyt danych Wczytanie punktów kolejnych zawodników // Czytaj punkty kolejnych zawodnikow for( nr_zawod = 0; nr_zawod < LB_ZAWOD; ++nr_zawod ) { cout << "Podaj punkty zawodnika nr: " << nr_zawod + 1 << endl; for( nr_konk = 0; nr_konk < LB_KONK; ++nr_konk ) { cout << '>'; cin >> punkty[ nr_zawod ][ nr_konk ]; } } Copyright Roman Simiński Strona : 102
Sumowanie Sumowanie punktów kolejnych zawodników // Sumuj punkty kolejnych zawodnikow for( nr_zawod = 0; nr_zawod < LB_ZAWOD; ++nr_zawod ) { punkty[ nr_zawod ][ SUMA ] = 0; for( nr_konk = 0; nr_konk < LB_KONK; ++nr_konk ) punkty[ nr_zawod ][ SUMA ] += punkty[ nr_zawod ][ nr_konk ]; } Copyright Roman Simiński Strona : 103
Wyprowadzanie sum Wyprowadzenie sum punktów kolejnych zawodników // Wyprowadz sumy punktów kolejnych zawodników cout << endl << "Sumy punktow zawodnikow"; for( nr_zawod = 0; nr_zawod < LB_ZAWOD; ++nr_zawod ) { cout << endl << nr_zawod + 1 << ": "; cout << punkty[ nr_zawod ][ SUMA ]; } Copyright Roman Simiński Strona : 104
Znajdowanie zwycięzcy Wyznaczanie maksimum wśród sum punktów // Wyznacz nalepszy wynik -- maksymalna sume maks = punkty[ nr_maks = 0 ][ SUMA ]; for( nr_zawod = 1; nr_zawod < LB_ZAWOD; ++nr_zawod ) if( punkty[ nr_zawod ][ SUMA ] > maks ) { nr_maks = nr_zawod; maks = punkty[ nr_zawod ][ SUMA ]; } cout << endl << "Wygrywa zawodnik nr : " << nr_maks + 1; cout << endl << "Jego suma punktów to: " << maks; Uwaga na mały trik: nr_maks = 0; maks = punkty[ nr_maks ][ SUMA ]; maks = punkty[ nr_maks = 0 ][ SUMA ]; Copyright Roman Simiński Strona : 105
Kompletny program #include <cstdlib> #include <iostream> using namespace std; int main() { const int LB_ZAWOD = 3; // Liczba zawodnikow const int LB_KONK = 5; // Liczba konkurencji const int SUMA = LB_KONK; // Indeks elem. z suma punktow // Dwuwymiarowa tablica punktów wszystkich zawodnikow int punkty[ LB_ZAWOD ][ LB_KONK + 1 ]; int nr_zawod, nr_konk; // Zmienne robocze iteracji int maks, nr_maks; // Minimum i nr minimum 1/3 Copyright Roman Simiński Strona : 106
Kompletny program // Czytaj i sumuj punkty kolejnych zawodnikow for( nr_zawod = 0; nr_zawod < LB_ZAWOD; ++nr_zawod ) { punkty[ nr_zawod ][ SUMA ] = 0; cout << "Podaj punkty zawodnika nr: " << nr_zawod + 1 << endl; for( nr_konk = 0; nr_konk < LB_KONK; ++nr_konk ) { cout << '>'; cin >> punkty[ nr_zawod ][ nr_konk ]; punkty[ nr_zawod ][ SUMA ] += punkty[ nr_zawod ][ nr_konk ]; }// for }// for // Wyprowadz sumy punktów kolejnych zawodników cout << endl << "Sumy punktow zawodnikow"; for( nr_zawod = 0; nr_zawod < LB_ZAWOD; ++nr_zawod ) { cout << endl << nr_zawod + 1 << ": "; cout << punkty[ nr_zawod ][ SUMA ]; } 2/3 Copyright Roman Simiński Strona : 107
Kompletny program // Wyznacz nalepszy wynik -- maksymalna sume maks = punkty[ nr_maks = 0 ][ SUMA ]; for( nr_zawod = 1; nr_zawod < LB_ZAWOD; ++nr_zawod ) if( punkty[ nr_zawod ][ SUMA ] > maks ) { nr_maks = nr_zawod; maks = punkty[ nr_zawod ][ SUMA ]; } cout << endl << "Wygrywa zawodnik nr : " << nr_maks + 1; cout << endl << "Jego suma punktów to: " << maks; cout << endl << "Nacisnij Enter by zakonczyc program"; } cin.ignore(); cin.get(); return EXIT_SUCCESS; 3/3 Copyright Roman Simiński Strona : 108
Kolejny program wytypuj szóstkę do dużego lotka Zadaniem programu jest wylosowanie sześciu liczb, pozwalających wypełnić pojedynczy typowanie tzw. dużego lotka. Losujemy liczby z przedziału 1.. 49, w wylosowanej szóstce nie może być powtórzeń. Copyright Roman Simiński Strona : 109
Wytypuj szóstkę do dużego lotka analiza + pseudokod Zdefiniuj zmienną całkowitą licznik losowanych liczb: wylosowanych Zdefiniuj zmienną całkowitą pamięta aktualnie wylosowaną liczbę: liczba Zainicjuj generator liczb pseudolosowych Wyzeruj zmienna wylosowanych Wykonuj Wylosuj wartość z przedzialu 1.. 49 i wstaw do zmiennej liczba Wyprowadź zawartość zmiennej liczba do strumienia wyjściowego Zwiększ zmienną wylosowanych o 1 Dopóki zmienna Wylosowanych ma wartość mniejszą od 6 To ma szansę zadziałać, ale nigdy nie wiadomo, czy losując kolejną liczbę, nie otrzymamy czasem którejś z już wcześniej wylosowanych liczb..., ale umówmy się, że ten problem rozwiążemy później. Copyright Roman Simiński Strona : 110
Wytypuj szóstkę do dużego lotka koślawa, pierwsza wersja #include <cstdlib> #include <ctime> #include <iostream> using namespace std; int main() { const int ZAKRES = 49; // Zakres losowanych liczb int liczba; // Losowana liczba, kandydat do szostki int wylosowanych; // Licznik losowanych liczb // Inicjalizacja gneratora liczb pseudolosowych srand( ( unsigned )time( 0 ) ); cout << "\nlosuje szostke liczb z 49-ciu."; cout << "\nwylosowana szostka:\n"; Copyright Roman Simiński Strona : 111
Wytypuj szóstkę do dużego lotka koślawa, pierwsza wersja // Zerowanie licznika wylosowanych liczb wylosowanych = 0; do { // Losowanie liczby z zakresu 1..49 liczba = rand() % ZAKRES + 1; // Wyprowadzenie wylosowanej liczby cout << liczba << ' '; ++wylosowanych; } while( wylosowanych < 6 ); } cout << "\n\nnacisnij Enter by zakonczyc program"; cin.get(); return EXIT_SUCCESS; Copyright Roman Simiński Strona : 112
Wytypuj szóstkę do dużego lotka jak wyeliminować duplikaty? Zdefiniuj zmienną całkowitą licznik losowanych liczb: wylosowanych Zdefiniuj zmienną całkowitą pamięta aktualnie wylosowaną liczbę: liczba Zainicjuj generator liczb pseudolosowych Wyzeruj zmienna wylosowanych Wykonuj Wylosuj wartość z przedzialu 1.. 49 i wstaw do zmiennej liczba Jeżeli wartość zmiennej Liczba nie była jeszcze wylosowana To Wyprowadź zawartość zmiennej liczba do strumienia wyjściowego Zwiększ zmienną wylosowanych o 1 Dopóki zmienna Wylosowanych ma wartość mniejszą od 6 W jaki sposób pamiętać, jakie liczby zostały wylosowane wcześniej? Copyright Roman Simiński Strona : 113
Wytypuj szóstkę do dużego lotka rejestr wylosowanych liczb Każdy Każdy element element rejestru rejestru odpowiada odpowiada liczbie liczbie kandydatce kandydatce do do szóstki. szóstki. Jeżeli Jeżeli na na danej danej pozycji pozycji w rejestrze rejestrze ustawiona ustawiona jest jest wartość wartość Tak, Tak, to to dana dana liczba liczba została została już już wylosowana. wylosowana. Jeżeli Jeżeli na na zadanej zadanej pozycji pozycji jest jest wartość wartość Nie, Nie, taka taka liczba liczba jeszcze jeszcze nie nie była była wylosowana. wylosowana. juzwylosowane juzwylosowane Tak Nie Tak Nie Tak... Nie Nie Tak Tak Nie 1 2 3 4 5 45 46 47 48 49 Załóżmy, Załóżmy, że że wylosowano wylosowano liczbę liczbę 45. 45. Na Na pozycji pozycji tej tej liczbie liczbie odpowiadającej odpowiadającej jest jest Nie, Nie, zatem zatem takiej takiej liczby liczby jeszcze jeszcze nie nie wylosowano. wylosowano. Liczba Liczba 45 45 może może wejść wejść do do losowanej losowanej szóstki. szóstki. Copyright Roman Simiński Strona : 114
Wytypuj szóstkę do dużego lotka rejestr wylosowanych liczb Każdy Każdy element element rejestru rejestru odpowiada odpowiada liczbie liczbie kandydatce kandydatce do do szóstki. szóstki. Jeżeli Jeżeli na na danej danej pozycji pozycji w rejestrze rejestrze ustawiona ustawiona jest jest wartość wartość Tak, Tak, to to dana dana liczba liczba została została już już wylosowana. wylosowana. Jeżeli Jeżeli na na zadanej zadanej pozycji pozycji jest jest wartość wartość Nie, Nie, taka taka liczba liczba jeszcze jeszcze nie nie była była wylosowana. wylosowana. juzwylosowane juzwylosowane Tak Nie Tak Nie Tak... Tak Nie Tak Tak Nie 1 2 3 4 5 45 46 47 48 49 Zaznaczamy, Zaznaczamy, że że liczba liczba 45 45 została została wylosowana wylosowana wpisując wpisując do do rejestru rejestru Tak, Tak, na na pozycji pozycji odpowiadającej odpowiadającej tej tej liczbie. liczbie. Copyright Roman Simiński Strona : 115
Wytypuj szóstkę do dużego lotka rejestr wylosowanych liczb Każdy Każdy element element rejestru rejestru odpowiada odpowiada liczbie liczbie kandydatce kandydatce do do szóstki. szóstki. Jeżeli Jeżeli na na danej danej pozycji pozycji w rejestrze rejestrze ustawiona ustawiona jest jest wartość wartość Tak, Tak, to to dana dana liczba liczba została została już już wylosowana. wylosowana. Jeżeli Jeżeli na na zadanej zadanej pozycji pozycji jest jest wartość wartość Nie, Nie, taka taka liczba liczba jeszcze jeszcze nie nie była była wylosowana. wylosowana. juzwylosowane juzwylosowane Tak Nie Tak Nie Tak... Tak Nie Tak Tak Nie 1 2 3 4 5 45 46 47 48 49 Załóżmy, Załóżmy, że że wylosowano wylosowano liczbę liczbę 5. 5. Na Na pozycji pozycji tej tej liczbie liczbie odpowiadającej odpowiadającej jest jest Tak, Tak, zatem zatem tę tę liczbę liczbę już już wylosowano. wylosowano. Liczba Liczba 5 5 zostaje zostaje odrzucona odrzucona jako jako dublet. dublet. Copyright Roman Simiński Strona : 116
Wytypuj szóstkę do dużego lotka rejestr wylosowanych liczb Każdy Każdy element element rejestru rejestru odpowiada odpowiada liczbie liczbie kandydatce kandydatce do do szóstki. szóstki. Jeżeli Jeżeli na na danej danej pozycji pozycji w rejestrze rejestrze ustawiona ustawiona jest jest wartość wartość Tak, Tak, to to dana dana liczba liczba została została już już wylosowana. wylosowana. Jeżeli Jeżeli na na zadanej zadanej pozycji pozycji jest jest wartość wartość Nie, Nie, taka taka liczba liczba jeszcze jeszcze nie nie była była wylosowana. wylosowana. juzwylosowane juzwylosowane Tak Nie Tak Nie Tak... Tak Nie Tak Tak Nie 1 2 3 4 5 45 46 47 48 49 Z Z rejestru rejestru wylosowanych wylosowanych liczb liczb można można wyczytać, wyczytać, które które z z nich nich zostały zostały wylosowane: wylosowane: 1 1 3 3 5 5 45 45 47 47 48 48 Copyright Roman Simiński Strona : 117
Rejestr wylosowanych liczb a język C++ Pierwszy problem indeksy tablic w C/C++ liczone są od zera: juzwylosowane juzwylosowane Tak Nie Tak Nie Tak... Tak Nie Tak Tak Nie 1 2 3 4 5 45 46 47 48 49 juzwylosowane juzwylosowane Tak Nie Tak Nie Tak... Tak Nie Tak Tak Nie 0 1 2 3 4 44 45 46 47 48 Drugi problem jak zapisać Tak/Nie w C++? W języku C++ istnieje zdefiniowany pierwotnie typ bool posiadający dwie dostepne wartości true prawda, tak oraz false fałsz, nie. const int ZAKRES = 49; // Zakres losowanych liczb bool juzwylosowane[ ZAKRES ]; // Rejestr wylosowanych liczb Copyright Roman Simiński Strona : 118