14. cvičení
Seřazení prvků pole dle velikosti
Nejjednodušší způsob, jak seřadit prvky pole dle velikosti, je použít jeden z následujících algoritmů:
Analýze těchto a dalších řadících algoritmů se budete věnovat v předmětu Základy algoritmizace (ZALG).
Probrané příklady
-
Seřazení prvků pole dle velikosti pomocí jednoduchého algoritmu. Hodnoty načtěte z terminálu nebo ze souboru.
Následující program provede řazení výběrem pomocí funkce
argmax
:#include <stdio.h> int argmax(int n, float* pole) { int vysledek = 0; for (int i = 0; i < n; i++) { if (pole[i] > pole[vysledek]) vysledek = i; } return vysledek; } void serad_pole(int n, float* pole) { for (int i = 0; i < n - 1; i++) { int m = argmax(n - i, pole + i); // prehodit pole[i] a pole[m + i] float pomocna = pole[i]; pole[i] = pole[m + i]; pole[m + i] = pomocna; } } int main() { printf("Zadej pocet cisel: "); int n; scanf("%d", &n); // pole o velikosti n float pole[n]; // nacist n cisel do pole for (int i = 0; i < n; i++) { scanf("%f", &pole[i]); } serad_pole(n, pole); // vypis n cisel for (int i = 0; i < n; i++) { printf("%f ", pole[i]); } printf("\n"); return 0; }
-
Seřazení tabulky (histogramu) počtu výskytů jednotlivých znaků v souboru (viz příklad z předchozího cvičení).
Oproti předchozímu příkladu v histogramu nestačí seřadit pole s počty výskytů každého znaku, protože bychom ztratili informaci o tom, kterému znaku daný počet výskytů přísluší. Problém lze vyřešit dvěma způsoby:
-
Nejjednodušší způsob je vytvořit druhé pole znaků a při řazení měnit pořadí prvků v obou polích, aby vždy platilo, že počet výskytů \(i\)-tého prvku nového pole je \(i\)-tý prvek původního pole.
#include <stdio.h> int argmax(int n, int* pole) { int vysledek = 0; for (int i = 0; i < n; i++) { if (pole[i] > pole[vysledek]) vysledek = i; } return vysledek; } void serad_pole(int n, int* pole, char* znaky) { for (int i = 0; i < n - 1; i++) { int m = argmax(n - i, pole + i); // prehodit pole[i] a pole[m + i] int pomocna = pole[i]; pole[i] = pole[m + i]; pole[m + i] = pomocna; // prehodit znaky[i] a znaky[m + i] char znak = znaky[i]; znaky[i] = znaky[m + i]; znaky[m + i] = znak; } } int main() { FILE* soubor = fopen("M:\\ZPRO 2019\\vstup.txt", "r"); if (soubor == NULL) { printf("chyba otevreni souboru\n"); return 1; } int pocty_vyskytu[256]; for (int i = 0; i < 256; i++) pocty_vyskytu[i] = 0; // dokud nedojdu na konec souboru while (!feof(soubor)) { // nacist znak int znak = fgetc(soubor); // pricist 1 v poli if (znak != EOF) pocty_vyskytu[znak]++; } fclose(soubor); char znaky[256]; for (int i = 0; i < 256; i++) znaky[i] = i; serad_pole(256, pocty_vyskytu, znaky); // vypis tabulky for (int i = 0; i < 256; i++) { if (pocty_vyskytu[i] == 0) break; printf("%d. nejcastejsi znak je '%c', pocet vyskytu: %d\n", i + 1, znaky[i], pocty_vyskytu[i]); } return 0; }
-
Alternativní způsob opět vyžaduje vytvořit další pole, ale nyní ne znaků, ale indexů. Při řazení budeme měnit pouze pořadí indexů a pořadí hodnot v původním poli (počty výskytů) zůstane nezměněné. Interpretace indexů bude taková, že \(i\)-tý prvek pole indexů udává číslo znaku s \(i\)-tým nejvyším počtem výskytů. Příslušný počet výskytů najdeme v původním poli pomocí čísla daného znaku.
#include <stdio.h> int argmax_2(int n, int* pole, int* indexy) { int vysledek = 0; for (int i = 0; i < n; i++) { if (pole[indexy[i]] > pole[indexy[vysledek]]) vysledek = i; } return vysledek; } void serad_pole_2(int n, int* pole, int* indexy) { for (int i = 0; i < n - 1; i++) { int m = argmax_2(n - i, pole, indexy + i); // prehodit indexy[i] a indexy[m + i] int znak = indexy[i]; indexy[i] = indexy[m + i]; indexy[m + i] = znak; } } int main() { FILE* soubor = fopen("M:\\ZPRO 2019\\vstup.txt", "r"); if (soubor == NULL) { printf("chyba otevreni souboru\n"); return 1; } int pocty_vyskytu[256]; for (int i = 0; i < 256; i++) pocty_vyskytu[i] = 0; // dokud nedojdu na konec souboru while (!feof(soubor)) { // nacist znak int znak = fgetc(soubor); // pricist 1 v poli if (znak != EOF) pocty_vyskytu[znak]++; } fclose(soubor); int indexy[256]; for (int i = 0; i < 256; i++) indexy[i] = i; serad_pole_2(256, pocty_vyskytu, indexy); // vypis tabulky for (int i = 0; i < 256; i++) { if (pocty_vyskytu[indexy[i]] == 0) break; printf("%d. nejcastejsi znak je '%c', pocet vyskytu: %d\n", i + 1, indexy[i], pocty_vyskytu[indexy[i]]); } return 0; }
-