Wykład 10 Przykłady różnych funkcji (cd) - przetwarzanie tablicy tablic (tablicy "dwuwymiarowej") - sortowanie przez "selekcję" Dynamiczna alokacja pamięci 1
// Liczy srednie w wierszach i kolumnach tablicy "dwuwymiarowej" // Elementy tablicy są generowane losowo #include <stdio.h> #include <stdlib.h> const int R = 8; // Liczba wierszy i kolumn double avgr(double T[][R], int r); // oblicza średnią w wierszu double avgc(double T[][R], int c); // oblicza średnią w kolumnie void Tfill(double T[][R]); // wypełnia tablicę danymi void Wyswietl(double T[][R]); // wyświetla zawartość tablicy double Tmax(double T[][R], int &w, int &k); // znajduje największy double Tmin(double T[][R], int &w, int &k); // znajduje najmniejszy int main(void) double X[R][R], W[R], K[R]; randomize(); // Inicjacja generatora losowego (Borland C++) Tfill(X); Wyswietl(X); for (int i = 0; i < R; i++) // Liczy średnie w wierszach W[i] = avgr(x, i); for (int j = 0; j < R; j++) // Liczy średnie w kolumnach K[j] = avgc(x, j); 2
// Wyświetlanie obliczonych średnich puts("srednie w wierszach: "); for (int r = 0; r < R; r++) printf("%5.1lf ", W[r]); puts("\nsrednie w kolumnach:"); for (int c = 0; c < R; c++) printf("%5.1lf ", K[c]); puts("\nsrednia na przekatnej:"); double ps = 0.0; for (int p = 0; p < R; p++) ps += X[p][p]; printf("%5.1lf\n", ps/r); puts("najwiekszy:"); double Tx; int wx, kx; // Numer wiersza i kolumny Tx = Tmax(X, wx, kx); // Referencje! printf("%5.1lf w miejscu [%d, %d]\n", Tx, wx, kx); puts("najmniejszy:"); Tx = Tmin(X, wx, kx); printf("%5.1lf w miejscu [%d, %d]\n", Tx, wx, kx); return 0; 3
void Wyswietl(double T[][R]) // Wyświetl zawartość tablicy for (int i = 0; i < R; i++) for (int j = 0; j < R; j++) printf("%6.1lf ", T[i][j]); printf("\n"); void Tfill(double T[][R]) // Generuj dane losowo for (int i = 0; i < R; i++) for (int j = 0; j < R; j++) T[i][j] = (double) (100.0*rand()/RAND_MAX); double avgr(double T[][R], int r) // Oblicz średnią w wierszu double suma = 0.0; for (int i = 0; i < R; i++) suma += T[r][i]; return suma/r; 4
double avgc(double T[][R], int c) // Oblicz średnią w kolumnie double suma = 0.0; for (int i = 0; i < R; i++) suma += T[i][c]; return suma/r; double Tmax(double T[][R], int &w, int &k) // Największy? double q = T[0][0]; w = 0; k = 0; for (int i = 0; i < R; i++) for (int j = 0; j < R; j++) if (q < T[i][j]) q = T[i][j]; w = i; k = j; return q; 5
double Tmin(double T[][R], int &w, int &k) // Najmniejszy? double q = T[0][0]; w = 0; k = 0; for (int i = 0; i < R; i++) for (int j = 0; j < R; j++) if (q > T[i][j]) q = T[i][j]; w = i; k = j; return q; 6
0.1 56.4 19.3 80.9 58.5 48.0 35.0 89.6 82.3 74.7 17.4 85.9 71.1 51.4 30.4 1.5 9.1 36.4 14.7 16.6 98.9 44.6 11.9 0.5 0.9 37.8 53.2 57.1 60.2 60.7 16.6 66.3 45.1 35.2 5.7 60.8 78.3 80.3 52.0 30.2 87.6 72.7 95.6 92.6 53.9 14.2 46.2 23.5 86.2 21.0 78.0 84.4 99.7 100.0 61.1 39.2 26.6 29.7 84.0 2.4 37.6 9.3 67.7 5.6 Srednie w wierszach: 48.5 51.8 29.1 44.1 48.4 60.8 71.2 32.9 Srednie w kolumnach: 42.2 45.5 46.0 60.1 69.8 51.0 40.1 32.1 Srednia na przekatnej: 38.2 Najwiekszy: 100.0 w miejscu [6, 5] Najmniejszy: 0.1 w miejscu [0, 0] 7
// Sortowanie przez selekcje #include <iostream.h> #include <stdlib.h> #include <conio.h> void display(int a[], int l, int r) // Wyświetlanie tablicy static int krok = 0; cout << "Cykl " << ++krok << ": "; for (int i=l; i<=r; i++) cout << a[i] << " "; cout << '\n'; getch(); void exch (int &A, int &B) // Zamiana elementów int t = A; A = B; B = t; void compexch(int &A, int &B) // Porównanie i zamiana if (B < A) exch (A, B); 8
void selection(int a[], int l, int r) for (int i = l; i < r; i++) int min = i; for (int j = i + 1; j <= r; j++) if (a[j] < a[min]) min = j; exch(a[i], a[min]); display(a, l, r); getch(); 9
int main(int argc, char *argv[]) // Rozmiar tablicy parametr randomize(); // Inicjacja generatora losowego (Borland C++) int i, n = atoi(argv[1]); int *a = new int[n]; // Dynamiczna alokacja pamięci for (i = 0; i < n; i++) a[i] = 1000*(1.0*rand()/RAND_MAX); cout << "Przed:" << endl; for (i = 0; i < n; i++) cout << a[i] << " "; cout << endl; selection(a, 0, n-1); cout << "Po:" << endl; for (i = 0; i < n; i++) cout << a[i] << " "; cout << endl; getch(); 10
Przed: 1 563 193 808 585 479 350 895 822 746 Cykl 1: 1 563 193 808 585 479 350 895 822 746 Cykl 2: 1 193 563 808 585 479 350 895 822 746 Cykl 3: 1 193 350 808 585 479 563 895 822 746 Cykl 4: 1 193 350 479 585 808 563 895 822 746 Cykl 5: 1 193 350 479 563 808 585 895 822 746 Cykl 6: 1 193 350 479 563 585 808 895 822 746 Cykl 7: 1 193 350 479 563 585 746 895 822 808 Cykl 8: 1 193 350 479 563 585 746 808 822 895 Cykl 9: 1 193 350 479 563 585 746 808 822 895 Po: 1 193 350 479 563 585 746 808 822 895 11
Funkcje dynamicznego przydziału i zwalniania pamięci Prototypy w alloc.h oraz stdlib.h void *malloc(size_t size) Funkcja ta przydziela w obszarze stosu zmiennych dynamicznych (tzw. sterta, ang. heap) blok pamięci o rozmiarze określonym parametrem size i zwraca jego adres. Konieczna jest konwersja (np. za pomocą rzutowania) tego adresu do typu właściwego dla typu alokowanego obiektu, np. char str = (char*) malloc(loo); Jeżeli system nie może przydzielić żądanego bloku pamięci, to zwraca adres pusty (NULL). void free(void *blok) Zwalnia blok pamięci wskazywany parametrem blok, przydzielony za pomocą funkcji malloc. 12
Operatory dynamicznego przydziału i zwalniania pamięci: Język C++ oprócz wymienionych wyżej funkcji dynamicznego przydziału i zwalniania pamięci posiada specjalne operatory: new - przydzialu pamięci oraz delete - zwalniania pamięci. Składnia wyrażeń z użyciem tych operatorów ma postać: new typ_obiektu Operator new tworzy obiekt typu (klasy) typ_obiektu, któremu przydziela sizeof typ_obiektu bajtów w obszarze sterty. Wartością tego wyrażenia jest wskaźnik na utworzony obiekt. W przypadku błędu zwraca adres pusty (NULL) delete wskaznik_obiektu Usuwa obiekt wskazywany przez wskaznik_obiektu. 13
// Alokacja i kasowanie tablicy #include <iostream.h> #include <conio.h> int main(void) float *p; int i, n = 15; p = new float [n]; // Alokacja pamięci for (i = 0; i < n; i++) p[i] = 100.0 - i; for (i = 0; i < n; i++) cout << p[i] << " "; cout << endl; delete [] p; // usuniecie tablicy return 0; 100 99 98 97 96 95 94 93 92 91 90 89 88 87 86 14