Diferență între revizuiri ale paginii „SDA Lucrarea 2 Backup”
Linia 14: | Linia 14: | ||
Pașii de rezolvare a unei probleme folosind ''Divide-et-impere'': | Pașii de rezolvare a unei probleme folosind ''Divide-et-impere'': | ||
+ | # Dacă problema este elementară, se întoarce direct rezultatul. | ||
# Se împarte problema inițială '''P''' (adică datele de intrare) în două probleme de același fel, '''P<sub>a</sub>''' și '''P<sub>b</sub>'''. În mod optim această împărțire se face exact la jumătate. | # Se împarte problema inițială '''P''' (adică datele de intrare) în două probleme de același fel, '''P<sub>a</sub>''' și '''P<sub>b</sub>'''. În mod optim această împărțire se face exact la jumătate. | ||
# Se rezolvă problemele '''P<sub>a</sub>''' și '''P<sub>b</sub>''' (folosind eventual același algoritm) și se obțin două rezultate parțiale '''R<sub>a</sub>''' și '''R<sub>b</sub>'''. | # Se rezolvă problemele '''P<sub>a</sub>''' și '''P<sub>b</sub>''' (folosind eventual același algoritm) și se obțin două rezultate parțiale '''R<sub>a</sub>''' și '''R<sub>b</sub>'''. | ||
# '''R<sub>a</sub>''' și '''R<sub>b</sub>''' se combină într-un mod care ține de aplicație și se obține rezultatul final '''R'''. | # '''R<sub>a</sub>''' și '''R<sub>b</sub>''' se combină într-un mod care ține de aplicație și se obține rezultatul final '''R'''. | ||
+ | |||
+ | De cele mai multe ori, algoritmii de tip ''divide-et-impera'' se implementează cu ajutorul funcțiilor recursive. | ||
+ | |||
+ | == Exemplu de algoritm și implementare == | ||
+ | |||
+ | === Cerință === | ||
+ | |||
+ | Se cere să se scrie un algoritm divide-et-impera care să calculeze maximul unui vector de valori în virgulă mobilă. | ||
+ | |||
+ | === Rezolvare === | ||
+ | |||
+ | # Dacă vectorul are un singur element, se întoarce elementul respectiv. | ||
+ | # Se împarte vectorul în două jumătăți egale (sau cel mult cu diferență de un element, dacă lungimea este impară). | ||
+ | # Se calculează maximul fiecărei jumătăți folosind același algoritm. | ||
+ | # Se calculează maximul global din maximul fiecărei jumătăți. | ||
+ | |||
+ | Implementarea în C: | ||
+ | <syntaxhighlight lang="C"> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | |||
+ | float getMaximum (float * array, unsigned start, unsigned stop) { | ||
+ | if (start == stop) return array[start]; | ||
+ | |||
+ | float max1 = getMaximum(array, start, (start + stop) / 2); | ||
+ | float max2 = getMaximum(array, (start + stop) / 2 + 1, stop); | ||
+ | |||
+ | return max1 > max2 ? max1 : max2; | ||
+ | } | ||
+ | |||
+ | int main(){ | ||
+ | unsigned size; | ||
+ | printf("size = "); | ||
+ | scanf("%u", &size); | ||
+ | |||
+ | float *array = (float*)malloc(size * sizeof(float)); | ||
+ | unsigned i; | ||
+ | for(i=0; i<size; i++) { | ||
+ | printf("array[%u] = ", i); | ||
+ | scanf("%f", &array[i]); | ||
+ | } | ||
+ | |||
+ | float max = getMaximum(array, 0, size - 1); | ||
+ | |||
+ | free(array); | ||
+ | |||
+ | printf("Max is = %f\n", max); | ||
+ | return 0; | ||
+ | } | ||
+ | </syntaxhighlight> |
Versiunea de la data 6 martie 2016 19:28
În acest laborator veți relua și recapitula noțiunile legate funcții recursive și citire și scriere din fișiere.
Utilizarea fișierelor in C
Pentru a recapitula modurile de scriere și citire din fișiere în limbajul C, puteți recapitula PC Laborator 13.
Funcțiile recursive - Clasa de algoritmi Divide-et-impera
Definirea și utilizarea funcțiilor recursive se pot recapitula citind PC Laborator 10.
Divide-et-impera
Clasa de algoritmi divide-et-impera se referă la algoritmii în care problema inițială se împarte în două probleme de același fel, în care datele de intrare nu se suprapun, se rezolvă aceste două subprobleme obținând două rezultate parțiale care apoi se combină pentru a obține rezultatul final.
Pașii de rezolvare a unei probleme folosind Divide-et-impere:
- Dacă problema este elementară, se întoarce direct rezultatul.
- Se împarte problema inițială P (adică datele de intrare) în două probleme de același fel, Pa și Pb. În mod optim această împărțire se face exact la jumătate.
- Se rezolvă problemele Pa și Pb (folosind eventual același algoritm) și se obțin două rezultate parțiale Ra și Rb.
- Ra și Rb se combină într-un mod care ține de aplicație și se obține rezultatul final R.
De cele mai multe ori, algoritmii de tip divide-et-impera se implementează cu ajutorul funcțiilor recursive.
Exemplu de algoritm și implementare
Cerință
Se cere să se scrie un algoritm divide-et-impera care să calculeze maximul unui vector de valori în virgulă mobilă.
Rezolvare
- Dacă vectorul are un singur element, se întoarce elementul respectiv.
- Se împarte vectorul în două jumătăți egale (sau cel mult cu diferență de un element, dacă lungimea este impară).
- Se calculează maximul fiecărei jumătăți folosind același algoritm.
- Se calculează maximul global din maximul fiecărei jumătăți.
Implementarea în C:
#include <stdio.h>
#include <stdlib.h>
float getMaximum (float * array, unsigned start, unsigned stop) {
if (start == stop) return array[start];
float max1 = getMaximum(array, start, (start + stop) / 2);
float max2 = getMaximum(array, (start + stop) / 2 + 1, stop);
return max1 > max2 ? max1 : max2;
}
int main(){
unsigned size;
printf("size = ");
scanf("%u", &size);
float *array = (float*)malloc(size * sizeof(float));
unsigned i;
for(i=0; i<size; i++) {
printf("array[%u] = ", i);
scanf("%f", &array[i]);
}
float max = getMaximum(array, 0, size - 1);
free(array);
printf("Max is = %f\n", max);
return 0;
}