<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="sk">
	<id>http://www.kiwiki.info/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Mstepanovsky</id>
	<title>Kiwiki - Príspevky používateľa [sk]</title>
	<link rel="self" type="application/atom+xml" href="http://www.kiwiki.info/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Mstepanovsky"/>
	<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php/%C5%A0peci%C3%A1lne:Pr%C3%ADspevky/Mstepanovsky"/>
	<updated>2026-05-03T19:31:04Z</updated>
	<subtitle>Príspevky používateľa</subtitle>
	<generator>MediaWiki 1.34.0</generator>
	<entry>
		<id>http://www.kiwiki.info/index.php?title=Triedenie(rie%C5%A1en%C3%A9_pr%C3%ADklady)&amp;diff=2353</id>
		<title>Triedenie(riešené príklady)</title>
		<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php?title=Triedenie(rie%C5%A1en%C3%A9_pr%C3%ADklady)&amp;diff=2353"/>
		<updated>2010-02-23T21:04:39Z</updated>

		<summary type="html">&lt;p&gt;Mstepanovsky: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Kategória:Študijné materiály]]&lt;br /&gt;
[[Kategória:Programovanie]]&lt;br /&gt;
[[Kategória:jazyk C]]&lt;br /&gt;
{{Draft}}&lt;br /&gt;
{{Skripta programovanie (zbierka úloh)}}&lt;br /&gt;
&lt;br /&gt;
==Triedenie poľa štruktúr==&lt;br /&gt;
'''Zadanie'''&lt;br /&gt;
&lt;br /&gt;
Zostavte program, ktorý bude triediť dáta uložené v súbore na základe užívateľom zadaného kritéria. Program po spustení načíta dáta zo súboru a uloží ich do poľa štruktúr. Následne na monitor zobrazí výzvu, v ktorej bude mať užívateľ možnosť vybrať kritérium triedenia. Pre jednoduchosť uvažujme príklad, v ktorom budeme triediť zamestnancov nejakej fiktívnej firmy podľa mena, priezviska alebo podľa roku jeho narodenia. Dáta v súbore nech sú uložené vo formáte kde jednotlivé položky sú oddelené medzerami čiarkami v tvare:&lt;br /&gt;
 Meno Priezvisko , Rok_narodenia &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
'''Metodický komentár'''&lt;br /&gt;
&lt;br /&gt;
Cieľom tejto úlohy je precvičiť prácu so štruktúrami v jazyku C, použitie funkcie rýchleho triedenia (quick sort) z knižnice ''stdlib.h'', načítavanie dát zo súboru, a pomôcť osvojiť si základné znalosti pri práci s ukazovateľmi (predávanie ako parameter do funkcie, pretypovávanie).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Vzorové dáta'''&lt;br /&gt;
 Janko Maly , 1978&lt;br /&gt;
 Martin Starsi , 1939&lt;br /&gt;
 Andrea Mlada , 1990&lt;br /&gt;
 Jozko Cierny , 1985&lt;br /&gt;
 Alenka Biela , 1985&lt;br /&gt;
 Janko Maly , 1983&lt;br /&gt;
 Alzbetka Mudra , 1978&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
'''Zjednodušujúce predpoklady'''&lt;br /&gt;
&lt;br /&gt;
Dĺžka mena ani priezviska neprekračuje rozsah 20 znakov. V zdrojovom súbore sa nebude nachádzať viac ako 100 záznamov. Zdrojový súbor sa nachádza v tom istom adresáry ako samotný program (*.exe súbor) a jeho názov je: data.txt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Vzorová výzva programu'''&lt;br /&gt;
 Vyber kriterium triedenia.&lt;br /&gt;
   Meno                     1&lt;br /&gt;
   Priezvisko               2&lt;br /&gt;
   Rok narodenia            3&lt;br /&gt;
   Pre ukoncenie programu   0&lt;br /&gt;
 Volba: _&lt;br /&gt;
	&lt;br /&gt;
'''Vzorový vstup'''&lt;br /&gt;
 1	&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
'''Vzorový výstup'''&lt;br /&gt;
 --------------------------------------------------------&lt;br /&gt;
  ZAMESTNANEC                               ROK NARODENIA&lt;br /&gt;
 --------------------------------------------------------&lt;br /&gt;
  Alenka               Biela                    1985&lt;br /&gt;
  Alzbetka             Mudra                    1978&lt;br /&gt;
  Andrea               Mlada                    1990&lt;br /&gt;
  Janko                Maly                     1983&lt;br /&gt;
  Janko                Maly                     1978&lt;br /&gt;
  Jozko                Cierny                   1985&lt;br /&gt;
  Martin               Starsi                   1939&lt;br /&gt;
 --------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Návod ako začať'''&lt;br /&gt;
&lt;br /&gt;
Zo zadania vyplýva, že hlavným účelom programu je triediť (vzostupne príp. zostupne zoradzovať) zamestnancov podľa triediaceho kritéria (meno, priezvisko, rok). Aby sme pri manipulácii (triedení) s jednotlivými zamestnancami pracovali ucelene so všetkými dátami vzťahujúcimi sa ku konkrétnemu zamestnancovi naraz, bude výhodné použiť štruktúru, ktorá nám tieto dáta takpovediac &amp;quot;zabalí&amp;quot;. Takto budeme mať údaje o jednom zamestnancovi pohromade a budeme môcť s nimi pohodlne manipulovať. Týmto sme vyriešili problém ako reprezentovať jedného zamestnanca. Teraz sa vynára otázka ako efektívne pracovať s celým súborom zamestnancov. Pretože vieme, že v zdrojovom súbore sa nebude nachádzať viac ako 100 zamestnancov, bude vcelku výhodné použiť statické pole štruktúr na pamätanie všetkých zamestnancov. Dĺžka tohto poľa bude 100 položiek. Jedna položka poľa potom bude predstavovať jedného konkrétneho zamestnanca. Utriedenie zamestnancov potom budeme realizovať utriedením tohto poľa. Pre triedenie poľa ponúka knižnica ''stdlib.h'' funkciu rýchleho triedenia ''qsort''. Parametre a použitie funkcie ''qsort'' z knižnice ''stdlib.h'' si teraz vysvetlíme.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Úplný funkčný prototyp funkcie ''qsort'' je nasledovný:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void qsort(void *base, size_t nelem, size_t width, int (*fcmp)(const void *, const void *));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Ako vidíme funkcia má štyri parametre, ktorých význam je:&lt;br /&gt;
*''base''  - ukazovateľ typu void ukazujúci na nultý element triedeného poľa &lt;br /&gt;
*''nelem'' - počet elementov v triedenom poli&lt;br /&gt;
*''width'' - veľkosť jedného elementu v bajtoch&lt;br /&gt;
*''fcmp''  - ukazovateľ na porovnávaciu funkciu, ktorá porovnáva dva elementy triedeného poľa&lt;br /&gt;
&lt;br /&gt;
Porovnávacia funkcia vyžaduje dva argumenty - ukazovatele typu ''const void *''. Označme tieto argumenty ''elem1'' a ''elem2''. Potom úplný funkčný prototyp porovnávacej funkcie bude:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
int (*fcmp)(const void *elem1, const void *elem2);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Od funkcie ''fcmp'' sa vyžaduje aby vracala celé číslo v závislosti od výsledku porovnania argumentov ''elem1'' a ''elem2'' nasledovne:&lt;br /&gt;
* ak *''elem1''  &amp;lt;  *''elem2''        potom ''fcmp'' vráti celé číslo &amp;lt; 0&lt;br /&gt;
* ak *''elem1''  == *''elem2''        potom ''fcmp'' vráti 0&lt;br /&gt;
* ak *''elem1''  &amp;gt;  *''elem2''        potom ''fcmp'' vráti celé číslo &amp;gt; 0&lt;br /&gt;
&lt;br /&gt;
Pri porovnávaní elementov elem1 a elem2 symbol &amp;lt; znamená, že elem1 je menší ako elem2 v tom zmysle, že v utriedenom poli sa elem1 nachádza pred elem2. Podobne pre symbol &amp;gt;. Ak sú porovnávané elementy z pohľadu triediaceho kritéria ekvivalenté (symbol ==) potom funkcia vráti nulu. Napríklad ak porovnávame dva reťazce a kritériom je abcedné usporiadanie, potom reťazec &amp;quot;Alexandra&amp;quot; je menší ako reťazec &amp;quot;Zora&amp;quot;. Ak by sme však chceli triediť podľa dĺžky reťazca, potom reťazec &amp;quot;Alexandra&amp;quot; je väčší ako reťazec &amp;quot;Zora&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Triedenie poľa sa potom realizuje volaním funkcie ''qsort'' s patričnými parametrami.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
''Poznámka'': Pri porovnávaní porovnávame obsahy argumentov ''elem1'' a ''elem2'', to znamená, že píšeme napr. *''elem1''  &amp;lt;  *''elem2'' namiesto ''elem1''  &amp;lt; ''elem2''. Zápis ''elem1''  &amp;lt;  ''elem2'' by totiž znamenal, že máme porovnať hodnotu ''elem1'' a ''elem2'' čo by znamenalo, že máme porovnať nejaké adresy uložené v premenných ''elem1'' a ''elem2'' (tieto premenné sú ukazovatele a teda pamätajú adresu, nie samotnú štruktúru). Porovnanie ''elem1''  &amp;lt;  ''elem2'' by teda bolo syntakticky správne, ale nemalo by zmysel. Chceme predsa porovnávať zamestnancov a nie adresy pamäte kde sú títo zamestnanci uložení. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Použitie funkcie ''qsort'' ilustrujeme na nasledujúcom jednoduchom príklade:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#define POCET_PRVKOV 6&lt;br /&gt;
&lt;br /&gt;
int pole[POCET_PRVKOV] = { 45, 11, 100, 30, 20, 27 };&lt;br /&gt;
&lt;br /&gt;
int Porovnaj_cele_cisla (const void * a, const void * b)&lt;br /&gt;
{&lt;br /&gt;
   // Parameter &amp;quot;a&amp;quot; je ukazovateľ typu &amp;quot;const void *&amp;quot;. Preto ho pred použitím musíme pretypovať na poiter na &amp;quot;int&amp;quot;. Čiže: &amp;quot;(int *)a&amp;quot;. &lt;br /&gt;
   // Pretože zápis &amp;quot;(int *)a&amp;quot; predstavuje ukazovateľ a my chceme porovnávať celé číslo, ktoré je uložené tam kde tento ukazovateľ ukazuje&lt;br /&gt;
   // musíme ďalej napísať: &amp;quot;*(int *)a&amp;quot;. Týmto zápisom sa dostaneme k hodnote čísla na ktoré ukazuje predaný parameter &amp;quot;const void * a&amp;quot;.&lt;br /&gt;
   // Podobne pre parameter &amp;quot;b&amp;quot;.&lt;br /&gt;
   return ( *(int*)a - *(int*)b );  &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main ()&lt;br /&gt;
{&lt;br /&gt;
  int n;&lt;br /&gt;
  // Vzostupné utriedenie poľa:&lt;br /&gt;
  qsort (pole, POCET_PRVKOV, sizeof(int), Porovnaj_cele_cisla);&lt;br /&gt;
&lt;br /&gt;
  // Výpis na monitor:&lt;br /&gt;
  for (n=0; n&amp;lt;POCET_PRVKOV; n++)&lt;br /&gt;
     printf (&amp;quot;%d &amp;quot;,values[n]);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Možné riešenie'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot; line &amp;gt;&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include&amp;lt;conio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NAZOV_SUBORU &amp;quot;data.txt&amp;quot;&lt;br /&gt;
&lt;br /&gt;
// Vytvorenie pomenovanej struktury s nazvom &amp;quot;ZAMESTNANEC&amp;quot;&lt;br /&gt;
struct ZAMESTNANEC {&lt;br /&gt;
   char meno[21];&lt;br /&gt;
   char priezvisko[21];&lt;br /&gt;
   int rok_narodenia;&lt;br /&gt;
   };&lt;br /&gt;
&lt;br /&gt;
// Uplne funkcne prototypy pouzivanych funkcii:&lt;br /&gt;
int nacitajZAMESTNANEC(FILE *fr, ZAMESTNANEC *V);	 // Nacitanie jedineho zamestnanca zo suboru&lt;br /&gt;
void vypisZAMESTNANEC(ZAMESTNANEC V);			 // Vypisanie jedineho zamestnanca na monitor&lt;br /&gt;
int porovnajROK(const void *V1, const void *V2);	 // Porovnanie dvoch zamestnancov podla roku narodenia&lt;br /&gt;
int porovnajMENO(const void *V1, const void *V2); 	 // Porovnanie dvoch zamestnancov podla mena&lt;br /&gt;
int porovnajPRIEZV(const void *V1, const void *V2);      // Porovnanie dvoch zamestnancov podla priezviska&lt;br /&gt;
&lt;br /&gt;
// Hlavna funkcia programu:&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
   ZAMESTNANEC pole[100];         // pole struktur pre uchovavanie jednotlivych zamestnancov&lt;br /&gt;
   int Pocet_zamestnancov = 0;    // pocet nacitanych zamestnancov&lt;br /&gt;
   int volba;                     // kriterium triedenia / ukoncenia programu&lt;br /&gt;
   FILE *fr;                      // pointer na subor&lt;br /&gt;
   int i;                         // pomocna premenna&lt;br /&gt;
   &lt;br /&gt;
   // Otvorenie zdrojoveho suboru v rezime &amp;quot;read&amp;quot;&lt;br /&gt;
   if((fr=fopen(NAZOV_SUBORU,&amp;quot;r&amp;quot;))==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;\n Pozadovany subor sa nepodarilo otvorit!\n&amp;quot;);&lt;br /&gt;
      system(&amp;quot;pause&amp;quot;);&lt;br /&gt;
      exit(1);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   // Nacitanie vsetkych zamestnancov zo suboru&lt;br /&gt;
   for(i=0; nacitajZAMESTNANEC(fr,&amp;amp;pole[i]); i++)&lt;br /&gt;
   {&lt;br /&gt;
      ;&lt;br /&gt;
   }&lt;br /&gt;
   Pocet_zamestnancov = i;&lt;br /&gt;
   fclose(fr); // zatvorenie suboru, data uz su nacitane..&lt;br /&gt;
   fr = NULL;  // zaroven nastavime na NULL pre pripad aby sme v pripade chybneho pouzitia tohto poitera boli vcas varovani&lt;br /&gt;
   &lt;br /&gt;
   // Hlavny cyklus programu &lt;br /&gt;
   do{&lt;br /&gt;
      printf(&amp;quot;\n Vyber kriterium triedenia. \n&amp;quot;&lt;br /&gt;
               &amp;quot;   Meno                     1\n&amp;quot;&lt;br /&gt;
	       &amp;quot;   Priezvisko               2\n&amp;quot;&lt;br /&gt;
	       &amp;quot;   Rok narodenia            3\n\n&amp;quot;&lt;br /&gt;
	       &amp;quot;   Pre ukoncenie programu   0\n\n&amp;quot;&lt;br /&gt;
               &amp;quot; Volba: &amp;quot;);&lt;br /&gt;
      scanf(&amp;quot;%d&amp;quot;,&amp;amp;volba);&lt;br /&gt;
      &lt;br /&gt;
      switch(volba)&lt;br /&gt;
      {&lt;br /&gt;
         case 0: break;&lt;br /&gt;
         case 1: qsort((void*)pole,Pocet_zamestnancov,sizeof(ZAMESTNANEC),porovnajMENO);   break; // namiesto sizeof(ZAMESTNANEC) mozeme pouzit sizeof(pole[0])&lt;br /&gt;
         case 2: qsort((void*)pole,Pocet_zamestnancov,sizeof(ZAMESTNANEC),porovnajPRIEZV); break;&lt;br /&gt;
         case 3: qsort((void*)pole,Pocet_zamestnancov,sizeof(ZAMESTNANEC),porovnajROK);    break;&lt;br /&gt;
         default:&lt;br /&gt;
            printf(&amp;quot;\n Neocakavany vstup. Program bude ukonceny.\n&amp;quot;);&lt;br /&gt;
            volba=0;&lt;br /&gt;
      }&lt;br /&gt;
      if(volba) // Vypisanie utriedeneho pola na monitor&lt;br /&gt;
      {&lt;br /&gt;
         clrscr(); //vycistime si obrazovku&lt;br /&gt;
         printf(&amp;quot;--------------------------------------------------------\n&amp;quot;);&lt;br /&gt;
         printf(&amp;quot; ZAMESTNANEC                               ROK NARODENIA\n&amp;quot;);&lt;br /&gt;
         printf(&amp;quot;--------------------------------------------------------\n&amp;quot;);&lt;br /&gt;
         for(i=0; i&amp;lt;Pocet_zamestnancov; i++)&lt;br /&gt;
            vypisZAMESTNANEC(pole[i]);&lt;br /&gt;
         printf(&amp;quot;--------------------------------------------------------\n&amp;quot;);&lt;br /&gt;
      }&lt;br /&gt;
   }while(volba);&lt;br /&gt;
&lt;br /&gt;
   system(&amp;quot;pause&amp;quot;);&lt;br /&gt;
   return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Definicie pouzivanych funkcii:&lt;br /&gt;
//---------------------------------------------------------------------------&lt;br /&gt;
int nacitajZAMESTNANEC(FILE *fr, ZAMESTNANEC *V)&lt;br /&gt;
{&lt;br /&gt;
   int a;&lt;br /&gt;
   a = fscanf(fr,&amp;quot;%s %s , %d&amp;quot;, V-&amp;gt;meno, V-&amp;gt;priezvisko, &amp;amp;V-&amp;gt;rok_narodenia);&lt;br /&gt;
   if(a == EOF) a = 0;&lt;br /&gt;
   return a;&lt;br /&gt;
}&lt;br /&gt;
//---------------------------------------------------------------------------&lt;br /&gt;
void vypisZAMESTNANEC(ZAMESTNANEC V)&lt;br /&gt;
{&lt;br /&gt;
   printf(&amp;quot; %-20s %-20s     %d\n&amp;quot;, V.meno, V.priezvisko, V.rok_narodenia);&lt;br /&gt;
}&lt;br /&gt;
//---------------------------------------------------------------------------&lt;br /&gt;
int porovnajROK(const void *V1, const void *V2)&lt;br /&gt;
{&lt;br /&gt;
   return ((ZAMESTNANEC*)V1)-&amp;gt;rok_narodenia - ((ZAMESTNANEC*)V2)-&amp;gt;rok_narodenia;&lt;br /&gt;
}&lt;br /&gt;
//---------------------------------------------------------------------------&lt;br /&gt;
int porovnajMENO(const void *V1, const void *V2)&lt;br /&gt;
{&lt;br /&gt;
   return strcmp(((ZAMESTNANEC*)V1)-&amp;gt;meno, ((ZAMESTNANEC*)V2)-&amp;gt;meno);&lt;br /&gt;
}&lt;br /&gt;
//---------------------------------------------------------------------------&lt;br /&gt;
int porovnajPRIEZV(const void *V1, const void *V2)&lt;br /&gt;
{&lt;br /&gt;
   return strcmp(((ZAMESTNANEC*)V1)-&amp;gt;priezvisko, ((ZAMESTNANEC*)V2)-&amp;gt;priezvisko);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Komentár k uvedenému riešeniu'''&lt;br /&gt;
&lt;br /&gt;
V programe sa na prvý pohľad nachádza zopár zvláštností. Prvou je  prázdne telo cyklu ''for'' pri načítavaní zamestnancov zo súboru - pozri riadok xx programu (nachádza sa tam len bodkočiarka za účelom zdôraznenia vedomého vypustenia tela funkcie). Dôvodom je, že samotné načítanie zamestnancov sa nachádza v porovnávacej (testovacej) časti cyklu ''for''. Ak sa úspešne načíta nejaký zamestnanec zo súboru potom funkcia ''nacitajZAMESTNANEC'' vracia nenulové kladné číslo, v opačnom prípade nulu a cyklus ''for'' sa skončí. Druhou zvláštnosťou je spôsob načítavania položiek &amp;quot;meno&amp;quot;, &amp;quot;priezvisko&amp;quot; a &amp;quot;rok_narodenia&amp;quot; v tele definicie funkcie ''nacitajZAMESTNANEC'' - pozri riadok xx. V tomto prípade s výhodou využívame možností funkcie ''fscanf'', pričom využívame skutočnosť, že jednotlivé položky sú oddelené medzerou a čiarkou. Treťou zvláštnosťou je použitie typu ''const void *'' v parametroch a následné pretypovávanie v tele na pointer na pomenovanú štruktúru ZAMESTNANEC vo všetkých troch porovnávacích funkciách - ''porovnajMENO'', ''porovnajPRIEZV'' a ''porovnajROK''. Toto priamo súvisí s požiadavkou na parametre porovnávacej funkcie, ktorá musí vyhovovať funkčnému prototypu funkcie triedenia - ''qsort''. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Nedostatky uvedeného riešenia a námety na zlepšenie'''&lt;br /&gt;
&lt;br /&gt;
Program nie je vhodný na triedenie väčšieho množstva dát. Pri triedení sa manipuluje s celými položkami (štruktúra ZAMESTNANEC), ktoré majú v tomto prípade veľkosť sizeof(ZAMESTNANEC) == 48 Bajtov. Funkcia ''qsort'' tak musí pri triedení kopírovať celý obsah, čo môže byť časovo náročné. Ak by navyše jednotlivé položky uchovávali ešte väčie množstvo dát (ďalšie údaje o zamestnancovi, ako napríklad pracovné zaradenie, osobné hodnotenie zamestnanca, kontaktné informácie a pod.) bola by situácia ešte horšia. Podobný nedostatok má aj funkcia vypisZAMESTNANEC. V tomto prípade však tento problém nie je kritický. Prvou možnosťou ako zefektívniť triedenie je redukovanie veľkosti štruktúry ZAMESTNANEC. To sa dá docieliť použitím dynamicky alokovanej pamäte pre uchovávanie mena a priezviska zamestnanca. V tomto prípade by mohla štruktúra ZAMESTNANEC vyzerať nasledovne:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot; &amp;gt;&lt;br /&gt;
struct ZAMESTNANEC {&lt;br /&gt;
   char *meno;&lt;br /&gt;
   char *priezvisko;&lt;br /&gt;
   int rok_narodenia;&lt;br /&gt;
   };&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Potom by sa pamäťové nároky na uchovávanie redukovali na 12 Bajtov. Je však nevyhnutné pamätať na to, že adresy uchovávané v položkách &amp;quot;meno&amp;quot; a &amp;quot;priezvisko&amp;quot; môžu byť ľubovolné (sú neinicializované) a preto môžu ukazovať na ľubovolné miesto v pamäti. Preto treba použiť dynamickú alokáciu pamäte (funkcia malloc, resp. operátor new) a ukazovatele &amp;quot;meno&amp;quot; a &amp;quot;priezvisko&amp;quot; správne nastaviť (využitím návratovej hodnoty funkcie malloc, resp. operátora new).&lt;br /&gt;
&lt;br /&gt;
Ďalšou možnosťou ako zefektívniť triedenie je použitie poľa ukazovateľov na prvky typu ZAMESTNANEC. Ukazovateľ na typ ZAMESTNANEC (či už pôvodný alebo tu uvedený) má veľkosť 4 Bajty. Z pohľadu triedenia funkciou qsort je preto tento spôsob ešte výhodnejší. &lt;br /&gt;
&lt;br /&gt;
Použitím kombinácie oboch možností (dynamicky alokovaný priestor pre uchovávenie jednotlivých záznamov typu ZAMESTNANEC a použitie poľa ukazovateľov na prvky typu ZAMESTNANEC pre účely triedenia) je možné dosiahuť hospodárne využitie pamäte a zároveň efektívne triedenie rozsiahlejšieho súboru dát.&lt;br /&gt;
&lt;br /&gt;
Druhou možnosťou sa zaoberá nasledujúca časť - Triedenie poľa ukazovateľov.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Triedenie poľa ukazovateľov ''aneb'' Triedime štruktúry efektívne==&lt;br /&gt;
'''Zadanie'''&lt;br /&gt;
&lt;br /&gt;
Uvažujme rovnaké zadanie ako v predošlom. Navyše požadujme viacúrovňové (vnorené) triedenie podľa triediaceho kritéria s nižšou prioritou ak sú položky podľa aktuálneho triediaceho kritéria ekvivalentné. V našom jednoduchom príklade to znamená, že ak napríklad triedime zamestnancov podľa krstného mena a mená niektorých zamestnancov sú rovnaké, potom budú títo utriedení podľa priezviska. Naopak, ak budeme triediť podľa priezviska a priezviská niektorých zamestnancov budú rovnaké, potom ich utriedime podľa krstného mena. Túto situáciu môžeme rozšíriť aj o triedenie podľa roku narodenia. V tomto prípade môžeme definovať prioritu jednotlivým triediacim kritériam a triediť následne podľa priorít.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Metodický komentár'''&lt;br /&gt;
&lt;br /&gt;
:Cieľom tejto úlohy v porovaní s predchádzajúcou je efektívne triediť dáta použitím ukazovateľov a poukázať na ďalšie možnosti pri ich triedení.  Využijú sa pokročilejšie techniky práce s ukazovateľmi, dynamická alokácia a realokácia pamäte. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Vzorové dáta'''&lt;br /&gt;
:Ako v predošlom.&lt;br /&gt;
	&lt;br /&gt;
&lt;br /&gt;
'''Zjednodušujúce predpoklady'''&lt;br /&gt;
&lt;br /&gt;
:Rovnaké ako v predošlom s tým rozdielom, že počet záznamov v súbore nie je obmedzený. Predpokladáme však, že systém má dostatok voľnej pamäte. &lt;br /&gt;
:V súbore sa teda môže nachádzať niekoľko desiatok, ale aj stoviek tisícov záznamov.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Vzorová výzva programu'''&lt;br /&gt;
 Vyber postupnost kriterii triedenia. (Prve kriterium ma najvacsiu prioritu.)&lt;br /&gt;
   Meno, Priezvisko, Rok    1&lt;br /&gt;
   Priezvisko, Meno, Rok    2&lt;br /&gt;
   Rok, Meno, Priezvisko    3&lt;br /&gt;
   Rok, Priezvisko, Meno    4&lt;br /&gt;
   Pre ukoncenie programu   0&lt;br /&gt;
 Volba: _&lt;br /&gt;
&lt;br /&gt;
'''Vzorový vstup'''&lt;br /&gt;
 1	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Vzorový výstup'''&lt;br /&gt;
 --------------------------------------------------------&lt;br /&gt;
  ZAMESTNANEC                               ROK NARODENIA&lt;br /&gt;
 --------------------------------------------------------&lt;br /&gt;
  Alenka               Biela                    1985&lt;br /&gt;
  Alzbetka             Mudra                    1978&lt;br /&gt;
  Andrea               Mlada                    1990&lt;br /&gt;
  Janko                Maly                     1978&lt;br /&gt;
  Janko                Maly                     1983&lt;br /&gt;
  Jozko                Cierny                   1985&lt;br /&gt;
  Martin               Starsi                   1939&lt;br /&gt;
 --------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Návod ako začať'''&lt;br /&gt;
&lt;br /&gt;
Prvým významným rozdielom v porovnaní s predchádzajúcim zadaním je skutočnosť, že počet záznamov (zamestnancov) v súbore nie je obmedzený a je vopred neznámy. Z toho dôvodu je použitie statického poľa štruktúr neefektívne. Riešením je dynamická alokácia pamäte. Mohli by sme tak dynamicky alokovať pole štruktúr podľa aktuálnej potreby programu. Ak sa však zamyslíme nad požiadavkou efektívneho triedenia zamestnancov prichádzame k záveru, že ani toto riešenie by nebolo vhodné. Dôvodom je činnosť funkcie ''qsort'', ktorá pri triedení manipuluje s celými položkami poľa, ktoré by v tomto prípade boli štruktúry (keďže by sa jednalo o pole štruktúr či už staticky alebo dynamicky alokované). Funkcia ''qsort'' by tak musela pracovať pri triedení s pomerne veľkým objemom dát. Riešením tejto situácie je použitie dynamicky alokovaného poľa ukazovateľov. Jednotlivé položky poľa by potom už neboli samotné štruktúry, ale adresy týchto štruktúr. Ako vieme, veľkosť adresy je 4 bajty (resp. 8B v 64-bitovom OS). Takže funkcia ''qsort'' bude triediť pole adries tak aby po zotriedení boli splnené požiadavky triedenia dané prioritami triediacich kritérií. Ak zhrnieme doteraz povedané, tak pre pamätanie celého súboru zamestnancov je výhodné použiť dynamicky alokované pole ukazovateľov, v ktorom pre každý prvok poľa budeme dynamicky alokovať pamäťový priestor pre pamätanie štruktúry uchovávajúcej údaje o jednom konkrétnom zamestnancovi.&lt;br /&gt;
&lt;br /&gt;
Druhým významným rozdielom je požiadavka na viacúrovňové triedenie. Pri písaní porovnávacích funkcií zohľadňujúcich tri úrovne priorít triediacih kritérií je výhodné začať od písania funkcií pre jednoúrovňové triedenie (pozri predchádzajúci príklad), tieto ďalej využiť pri písaní dvojúrovňových, a tieto spolu zasa pri písaní trojúrovňových. Takto môžeme veľmi jednoducho a prehľadne podľa potreby napísať rôzne mnohoúrovňové porovnávacie funkcie.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Možné riešenie'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot; line &amp;gt;&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include&amp;lt;conio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NAZOV_SUBORU &amp;quot;data.txt&amp;quot;&lt;br /&gt;
#define KROK_REALOKACIE 100&lt;br /&gt;
&lt;br /&gt;
// Vytvorenie pomenovanej struktury s nazvom &amp;quot;ZAMESTNANEC&amp;quot;&lt;br /&gt;
struct ZAMESTNANEC {&lt;br /&gt;
   char meno[21];&lt;br /&gt;
   char priezvisko[21];&lt;br /&gt;
   int rok_narodenia;&lt;br /&gt;
   };&lt;br /&gt;
&lt;br /&gt;
// Uplne funkcne prototypy pouzivanych funkcii:&lt;br /&gt;
int nacitajZAMESTNANEC(FILE *fr, ZAMESTNANEC *V);	      // Nacitanie jedineho zamestnanca zo suboru&lt;br /&gt;
void vypisZAMESTNANEC(ZAMESTNANEC V);			      // Vypisanie jedineho zamestnanca na monitor&lt;br /&gt;
int porovnajROK(const void *V1, const void *V2);	      // Porovnanie dvoch zamestnancov podla roku narodenia&lt;br /&gt;
int porovnajMENO(const void *V1, const void *V2); 	      // Porovnanie dvoch zamestnancov podla mena&lt;br /&gt;
int porovnajPRIEZV(const void *V1, const void *V2);           // Porovnanie dvoch zamestnancov podla priezviska&lt;br /&gt;
int porovnajPRIEZV_MENO(const void *V1, const void *V2);      // Porovnanie najprv podla priezviska potom podla mena&lt;br /&gt;
int porovnajMENO_PRIEZV(const void *V1, const void *V2);      // podobne dalej...&lt;br /&gt;
int porovnajMENO_PRIEZV_ROK(const void *V1, const void *V2);&lt;br /&gt;
int porovnajPRIEZV_MENO_ROK(const void *V1, const void *V2);&lt;br /&gt;
int porovnajROK_PRIEZV_MENO(const void *V1, const void *V2);&lt;br /&gt;
int porovnajROK_MENO_PRIEZV(const void *V1, const void *V2);&lt;br /&gt;
&lt;br /&gt;
// Hlavna funkcia programu:&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
   ZAMESTNANEC **pole;                          // Pozor, zmena v porovnani s predchadzajucim riesenim!&lt;br /&gt;
   int Pocet_zamestnancov = 0;                  // Pocet nacitanych zamestnancov &lt;br /&gt;
   int maxPocet_zamestnancov = 100;             // Prednastaveny maximalny pocet zamestnancov&lt;br /&gt;
   int volba;                                   // kriterium triedenia / ukoncenia programu&lt;br /&gt;
   FILE *fr;                                    // pointer na zdrojovy subor, z ktoreho budeme nacitavat zamestnancov&lt;br /&gt;
   int (*sortFun)(const void *,const void *);   // pointer na funkciu, pomocou ktorej budeme triedit&lt;br /&gt;
   int i;                                       // pomocna premenna&lt;br /&gt;
   &lt;br /&gt;
   // Otvorenie zdrojoveho suboru v rezime &amp;quot;read&amp;quot;&lt;br /&gt;
   if((fr=fopen(NAZOV_SUBORU,&amp;quot;r&amp;quot;))==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;\n Pozadovany subor sa nepodarilo otvorit!\n&amp;quot;);&lt;br /&gt;
      system(&amp;quot;pause&amp;quot;);&lt;br /&gt;
      exit(1);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   // Prvotna alokacia pamate pre pole pointrov na pomenovanu strukturu ZAMESTNANEC&lt;br /&gt;
   if((pole=(ZAMESTNANEC**)malloc(maxPocet_zamestnancov*sizeof(ZAMESTNANEC*)))==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot; Nedostatok pamate!\n&amp;quot;);&lt;br /&gt;
      system(&amp;quot;pause&amp;quot;);&lt;br /&gt;
      exit(1);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   //Najprv si musime alokovat priestor pre prveho zamestnanca (aby data, ktore nacitame sme mali kam ulozit)&lt;br /&gt;
   if((pole[0]=(ZAMESTNANEC*)malloc(sizeof(ZAMESTNANEC)))==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;\n Nedostatok pamete...\n&amp;quot;);&lt;br /&gt;
      exit(1);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   // Nacitanie vsetkych zamestnancov zo suboru&lt;br /&gt;
   for(i=0; nacitajZAMESTNANEC(fr,pole[i]); i++)&lt;br /&gt;
   {&lt;br /&gt;
		//Alokujeme si miesto pre dalsieho zamestnanca:&lt;br /&gt;
      if((pole[i+1]=(ZAMESTNANEC*)malloc(sizeof(ZAMESTNANEC)))==NULL)&lt;br /&gt;
      {&lt;br /&gt;
         printf(&amp;quot;\n Nedostatok pamete pre pridanie dalsieho zamestnanca...\n&amp;quot;);&lt;br /&gt;
         system(&amp;quot;pause&amp;quot;);&lt;br /&gt;
         exit(1);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // V pripade potreby realokujeme pole pinterov: (Tato situacia nastane&lt;br /&gt;
      // ak pocet zamestnancov v subore je vacsi ako aktualne nastavna hodnota&lt;br /&gt;
      // premennej maxPocet_zamestnancov)&lt;br /&gt;
      if(i == maxPocet_zamestnancov-2)&lt;br /&gt;
      {&lt;br /&gt;
         maxPocet_zamestnancov += KROK_REALOKACIE;  // Zvysime maximalny pocet zamestnancov&lt;br /&gt;
         //printf(&amp;quot;...realokujem...&amp;quot;);&lt;br /&gt;
         if((pole=(ZAMESTNANEC**)realloc(pole,maxPocet_zamestnancov*sizeof(ZAMESTNANEC*)))==NULL)&lt;br /&gt;
         {&lt;br /&gt;
            printf(&amp;quot; Nedostatok pamate pre realokaciu pola pointerov!\n&amp;quot;);&lt;br /&gt;
            system(&amp;quot;pause&amp;quot;);&lt;br /&gt;
            exit(1);&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   Pocet_zamestnancov = i;&lt;br /&gt;
   fclose(fr); // zatvorenie suboru, data uz su nacitane..&lt;br /&gt;
   fr = NULL;  // zaroven nastavime na NULL pre pripad aby sme v pripade chybneho pouzitia tohto poitera boli vcas varovani&lt;br /&gt;
   &lt;br /&gt;
   // Hlavny cyklus programu &lt;br /&gt;
   do{&lt;br /&gt;
      printf(&amp;quot;\n Vyber postupnost kriterii triedenia. (Prve kriterium ma najvacsiu prioritu.)\n&amp;quot;&lt;br /&gt;
	       &amp;quot;   Meno, Priezvisko, Rok    1\n&amp;quot;&lt;br /&gt;
	       &amp;quot;   Priezvisko, Meno, Rok    2\n&amp;quot;&lt;br /&gt;
	       &amp;quot;   Rok, Meno, Priezvisko    3\n&amp;quot;&lt;br /&gt;
               &amp;quot;   Rok, Priezvisko, Meno    4\n\n&amp;quot;&lt;br /&gt;
	       &amp;quot;   Pre ukoncenie programu   0\n\n&amp;quot;&lt;br /&gt;
	       &amp;quot; Volba: &amp;quot;);&lt;br /&gt;
      scanf(&amp;quot;%d&amp;quot;,&amp;amp;volba);&lt;br /&gt;
      &lt;br /&gt;
      switch(volba)&lt;br /&gt;
      {&lt;br /&gt;
         case 0: break;&lt;br /&gt;
         case 1: sortFun = porovnajMENO_PRIEZV_ROK;   break;&lt;br /&gt;
         case 2: sortFun = porovnajPRIEZV_MENO_ROK;   break;&lt;br /&gt;
         case 3: sortFun = porovnajROK_MENO_PRIEZV;   break;&lt;br /&gt;
         case 4: sortFun = porovnajROK_PRIEZV_MENO;   break;&lt;br /&gt;
         default:&lt;br /&gt;
            printf(&amp;quot;\n Neocakavany vstup. Program bude ukonceny.\n&amp;quot;);&lt;br /&gt;
            volba=0;&lt;br /&gt;
      }&lt;br /&gt;
      if(volba) // Vypisanie utriedeneho pola na monitor&lt;br /&gt;
      {&lt;br /&gt;
         // Utriedenie zamestnancov:&lt;br /&gt;
         qsort((void*)pole,Pocet_zamestnancov,sizeof(pole[0]),sortFun);&lt;br /&gt;
&lt;br /&gt;
         clrscr(); //vycistime si obrazovku&lt;br /&gt;
         printf(&amp;quot;--------------------------------------------------------\n&amp;quot;);&lt;br /&gt;
         printf(&amp;quot; ZAMESTNANEC                               ROK NARODENIA\n&amp;quot;);&lt;br /&gt;
         printf(&amp;quot;--------------------------------------------------------\n&amp;quot;);&lt;br /&gt;
         for(i=0;i&amp;lt;Pocet_zamestnancov;i++)&lt;br /&gt;
            vypisZAMESTNANEC(*pole[i]);&lt;br /&gt;
         printf(&amp;quot;--------------------------------------------------------\n&amp;quot;);&lt;br /&gt;
      }&lt;br /&gt;
   }while(volba);&lt;br /&gt;
&lt;br /&gt;
   // Na zaver nasleduje uvolnenie pamate, ktoru sme alokovali.&lt;br /&gt;
   // Najprv musime uvolnit pamet, ktoru sme alokovali pre jednotlivych zamestnancov.&lt;br /&gt;
   for(i=0; i&amp;lt;skutocnyPocet_zamestnancov + 1;i++) //Pocet alokovanych zamestnancov je o jednehoneho viac...&lt;br /&gt;
      free(pole[i]);&lt;br /&gt;
&lt;br /&gt;
   //Potom uvolnime pamat alokovanu pre pointre&lt;br /&gt;
   free(pole);&lt;br /&gt;
   poleStud = NULL;  // a nastavime na NULL (nie je nevyhnutne potrebne)&lt;br /&gt;
   &lt;br /&gt;
   system(&amp;quot;pause&amp;quot;);&lt;br /&gt;
   return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Definicie pouzivanych funkcii:&lt;br /&gt;
//---------------------------------------------------------------------------&lt;br /&gt;
int nacitajZAMESTNANEC(FILE *fr, ZAMESTNANEC *V)&lt;br /&gt;
{&lt;br /&gt;
   int a;&lt;br /&gt;
   a = fscanf(fr,&amp;quot;%s %s , %d&amp;quot;, V-&amp;gt;meno, V-&amp;gt;priezvisko, &amp;amp;V-&amp;gt;rok_narodenia);&lt;br /&gt;
   if(a == EOF) a = 0;&lt;br /&gt;
   return a;&lt;br /&gt;
}&lt;br /&gt;
//---------------------------------------------------------------------------&lt;br /&gt;
void vypisZAMESTNANEC(ZAMESTNANEC V)&lt;br /&gt;
{&lt;br /&gt;
   printf(&amp;quot; %-20s %-20s     %d\n&amp;quot;, V.meno, V.priezvisko, V.rok_narodenia);&lt;br /&gt;
}&lt;br /&gt;
//---------------------------------------------------------------------------&lt;br /&gt;
int porovnajROK(const void *V1, const void *V2)&lt;br /&gt;
{&lt;br /&gt;
   return (*(ZAMESTNANEC**)V1)-&amp;gt;rok_narodenia - (*(ZAMESTNANEC**)V2)-&amp;gt;rok_narodenia;&lt;br /&gt;
}&lt;br /&gt;
//---------------------------------------------------------------------------&lt;br /&gt;
int porovnajMENO(const void *V1, const void *V2)&lt;br /&gt;
{&lt;br /&gt;
   return strcmp((*(ZAMESTNANEC**)V1)-&amp;gt;meno, (*(ZAMESTNANEC**)V2)-&amp;gt;meno);&lt;br /&gt;
}&lt;br /&gt;
//---------------------------------------------------------------------------&lt;br /&gt;
int porovnajPRIEZV(const void *V1, const void *V2)&lt;br /&gt;
{&lt;br /&gt;
   return strcmp((*(ZAMESTNANEC**)V1)-&amp;gt;priezvisko, (*(ZAMESTNANEC**)V2)-&amp;gt;priezvisko);&lt;br /&gt;
}&lt;br /&gt;
//---------------------------------------------------------------------------&lt;br /&gt;
int porovnajPRIEZV_MENO(const void *V1, const void *V2)&lt;br /&gt;
{&lt;br /&gt;
   int a = porovnajPRIEZV(V1, V2);&lt;br /&gt;
   if(a == 0) a = porovnajMENO(V1, V2);&lt;br /&gt;
   return a;&lt;br /&gt;
}&lt;br /&gt;
//---------------------------------------------------------------------------&lt;br /&gt;
int porovnajMENO_PRIEZV(const void *V1, const void *V2)&lt;br /&gt;
{&lt;br /&gt;
   int a = porovnajMENO(V1, V2);&lt;br /&gt;
   if(a == 0) a = porovnajPRIEZV(V1, V2);&lt;br /&gt;
   return a;&lt;br /&gt;
}&lt;br /&gt;
//---------------------------------------------------------------------------&lt;br /&gt;
int porovnajMENO_PRIEZV_ROK(const void *V1, const void *V2)&lt;br /&gt;
{&lt;br /&gt;
   int a = porovnajMENO_PRIEZV(V1, V2);&lt;br /&gt;
   if(a == 0) a = porovnajROK(V1, V2);&lt;br /&gt;
   return a;&lt;br /&gt;
}&lt;br /&gt;
//---------------------------------------------------------------------------&lt;br /&gt;
int porovnajPRIEZV_MENO_ROK(const void *V1, const void *V2)&lt;br /&gt;
{&lt;br /&gt;
   int a = porovnajPRIEZV_MENO(V1, V2);&lt;br /&gt;
   if(a == 0) a = porovnajROK(V1, V2);&lt;br /&gt;
   return a;&lt;br /&gt;
}&lt;br /&gt;
//---------------------------------------------------------------------------&lt;br /&gt;
int porovnajROK_PRIEZV_MENO(const void *V1, const void *V2)&lt;br /&gt;
{&lt;br /&gt;
   int a = porovnajROK(V1, V2);&lt;br /&gt;
   if(a == 0) a = porovnajPRIEZV_MENO(V1, V2);&lt;br /&gt;
   return a;&lt;br /&gt;
}&lt;br /&gt;
//---------------------------------------------------------------------------&lt;br /&gt;
int porovnajROK_MENO_PRIEZV(const void *V1, const void *V2)&lt;br /&gt;
{&lt;br /&gt;
   int a = porovnajROK(V1, V2);&lt;br /&gt;
   if(a == 0) a = porovnajMENO_PRIEZV(V1, V2);&lt;br /&gt;
   return a;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Komentár k uvedenému riešeniu'''&lt;br /&gt;
&lt;br /&gt;
Bude zverejnený neskôr.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Nedostatky uvedeného riešenia a námety na zlepšenie'''&lt;br /&gt;
&lt;br /&gt;
Program nie je vhodný na triedenie extrémne rozsiahlych dát. Riešením tohto nedostatku je použitie iných triediacich funkcií, ktoré pracujú na princípe triedenia triedeného súboru po častiach. Ďalším nedostatkom je výpis utriedených dát na monitor. Táto operácia môže byť pri väčšom počte záznamov časovo veľmi zdĺhavá. Oveľa výhodnejšie a zároveň rýchlejšie je zapisovať výsledky do súboru. V tomto prípade by postačovalo modifikovať funkciu ''vypisZAMESTNANEC'' tak, aby vyhovovala tomuto účelu. &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
vypisZAMESTNANEC(FILE *fw, ZAMESTNANEC *V)&lt;br /&gt;
{&lt;br /&gt;
   fprintf(fw,&amp;quot; %-20s %-20s     %d\n&amp;quot;, V-&amp;gt;meno, V-&amp;gt;priezvisko, V-&amp;gt;rok_narodenia);  // Zaroven efektivnejsie pristupujeme k polozkam zamestnanca (parameter V je pointer...)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ak by sme si ďalej zadefinovali funkciu na výpis všetkých zamestnancov celý program by sme zjednodušili a výpis zamestnancov by bol univerzálnejší v tom zmysle, že výpis zamestnancov či už do súboru alebo na monitor by mal jednotnú podobu. Funkcia na výpis všetkých zamestnancov by mohla vyzerať nasledovne:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
vypisZAMESTNANCOV(FILE *fw, ZAMESTNANEC **pole, int Pocet_zamestnancov)&lt;br /&gt;
{&lt;br /&gt;
   printf(&amp;quot;--------------------------------------------------------\n&amp;quot;);&lt;br /&gt;
   printf(&amp;quot; ZAMESTNANEC                               ROK NARODENIA\n&amp;quot;);&lt;br /&gt;
   printf(&amp;quot;--------------------------------------------------------\n&amp;quot;);&lt;br /&gt;
   for(i=0;i&amp;lt;Pocet_zamestnancov;i++)&lt;br /&gt;
      vypisZAMESTNANEC(fw, pole[i]);&lt;br /&gt;
   printf(&amp;quot;--------------------------------------------------------\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Potom by jednoducho stačilo otvoriť nejaký súbor v režime &amp;quot;write&amp;quot; a zavolať túto funkciu na zápis všetkých zamestnancov do súboru. Ak by sme však chceli vypísať zamestnancov na monitor, potom namiesto ukazovateľa na otvorený súbor zadáme ''stdout''. Čiže do programu vložíme riadok:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
   vypisZAMESTNANCOV(stdout,pole,Pocet_zamestnancov);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mstepanovsky</name></author>
		
	</entry>
	<entry>
		<id>http://www.kiwiki.info/index.php?title=Triedenie(rie%C5%A1en%C3%A9_pr%C3%ADklady)&amp;diff=2351</id>
		<title>Triedenie(riešené príklady)</title>
		<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php?title=Triedenie(rie%C5%A1en%C3%A9_pr%C3%ADklady)&amp;diff=2351"/>
		<updated>2010-02-23T16:01:43Z</updated>

		<summary type="html">&lt;p&gt;Mstepanovsky: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Kategória:Študijné materiály]]&lt;br /&gt;
[[Kategória:Programovanie]]&lt;br /&gt;
[[Kategória:jazyk C]]&lt;br /&gt;
{{Draft}}&lt;br /&gt;
{{Skripta programovanie (zbierka úloh)}}&lt;br /&gt;
&lt;br /&gt;
==Triedenie poľa štruktúr==&lt;br /&gt;
'''Zadanie'''&lt;br /&gt;
&lt;br /&gt;
Zostavte program, ktorý bude triediť dáta uložené v súbore na základe užívateľom zadaného kritéria. Program po spustení načíta dáta zo súboru a uloží ich do poľa štruktúr. Následne na monitor zobrazí výzvu, v ktorej bude mať užívateľ možnosť vybrať kritérium triedenia. Pre jednoduchosť uvažujme príklad, v ktorom budeme triediť zamestnancov nejakej fiktívnej firmy podľa mena, priezviska alebo podľa roku jeho narodenia. Dáta v súbore nech sú uložené vo formáte kde jednotlivé položky sú oddelené medzerami čiarkami v tvare:&lt;br /&gt;
 Meno Priezvisko , Rok_narodenia &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
'''Metodický komentár'''&lt;br /&gt;
&lt;br /&gt;
Cieľom tejto úlohy je precvičiť prácu so štruktúrami v jazyku C, použitie funkcie rýchleho triedenia (quick sort) z knižnice ''stdlib.h'', načítavanie dát zo súboru, a pomôcť osvojiť si základné znalosti pri práci s ukazovateľmi (predávanie ako parameter do funkcie, pretypovávanie).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Vzorové dáta'''&lt;br /&gt;
 Janko Maly , 1978&lt;br /&gt;
 Martin Starsi , 1939&lt;br /&gt;
 Andrea Mlada , 1990&lt;br /&gt;
 Jozko Cierny , 1985&lt;br /&gt;
 Alenka Biela , 1985&lt;br /&gt;
 Janko Maly , 1983&lt;br /&gt;
 Alzbetka Mudra , 1978&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
'''Zjednodušujúce predpoklady'''&lt;br /&gt;
&lt;br /&gt;
Dĺžka mena ani priezviska neprekračuje rozsah 20 znakov. V zdrojovom súbore sa nebude nachádzať viac ako 100 záznamov. Zdrojový súbor sa nachádza v tom istom adresáry ako samotný program (*.exe súbor) a jeho názov je: data.txt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Vzorová výzva programu'''&lt;br /&gt;
 Vyber kriterium triedenia.&lt;br /&gt;
   Meno                     1&lt;br /&gt;
   Priezvisko               2&lt;br /&gt;
   Rok narodenia            3&lt;br /&gt;
   Pre ukoncenie programu   0&lt;br /&gt;
 Volba: _&lt;br /&gt;
	&lt;br /&gt;
'''Vzorový vstup'''&lt;br /&gt;
 1	&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
'''Vzorový výstup'''&lt;br /&gt;
 --------------------------------------------------------&lt;br /&gt;
  ZAMESTNANEC                               ROK NARODENIA&lt;br /&gt;
 --------------------------------------------------------&lt;br /&gt;
  Alenka               Biela                    1985&lt;br /&gt;
  Alzbetka             Mudra                    1978&lt;br /&gt;
  Andrea               Mlada                    1990&lt;br /&gt;
  Janko                Maly                     1983&lt;br /&gt;
  Janko                Maly                     1978&lt;br /&gt;
  Jozko                Cierny                   1985&lt;br /&gt;
  Martin               Starsi                   1939&lt;br /&gt;
 --------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Návod ako začať'''&lt;br /&gt;
&lt;br /&gt;
Zo zadania vyplýva, že hlavným účelom programu je triediť (vzostupne príp. zostupne zoradzovať) zamestnancov podľa triediaceho kritéria (meno, priezvisko, rok). Aby sme pri manipulácii (triedení) s jednotlivými zamestnancami pracovali ucelene so všetkými dátami vzťahujúcimi sa ku konkrétnemu zamestnancovi naraz, bude výhodné použiť štruktúru, ktorá nám tieto dáta takpovediac &amp;quot;zabalí&amp;quot;. Takto budeme mať údaje o jednom zamestnancovi pohromade a budeme môcť s nimi pohodlne manipulovať. Týmto sme vyriešili problém ako reprezentovať jedného zamestnanca. Teraz sa vynára otázka ako efektívne pracovať s celým súborom zamestnancov. Pretože vieme, že v zdrojovom súbore sa nebude nachádzať viac ako 100 zamestnancov, bude vcelku výhodné použiť statické pole štruktúr na pamätanie všetkých zamestnancov. Dĺžka tohto poľa bude 100 položiek. Jedna položka poľa potom bude predstavovať jedného konkrétneho zamestnanca. Utriedenie zamestnancov potom budeme realizovať utriedením tohto poľa. Pre triedenie poľa ponúka knižnica ''stdlib.h'' funkciu rýchleho triedenia ''qsort''. Parametre a použitie funkcie ''qsort'' z knižnice ''stdlib.h'' si teraz vysvetlíme.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Úplný funkčný prototyp funkcie ''qsort'' je nasledovný:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void qsort(void *base, size_t nelem, size_t width, int (*fcmp)(const void *, const void *));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Ako vidíme funkcia má štyri parametre, ktorých význam je:&lt;br /&gt;
*''base''  - pointer typu void ukazujúci na nultý element triedeného poľa &lt;br /&gt;
*''nelem'' - počet elementov v triedenom poli&lt;br /&gt;
*''width'' - veľkosť jedného elementu v bajtoch&lt;br /&gt;
*''fcmp''  - pointer na porovnávaciu funkciu, ktorá porovnáva dva elementy triedeného poľa&lt;br /&gt;
&lt;br /&gt;
Porovnávacia funkcia vyžaduje dva argumenty - pointery typu ''const void *''. Označme tieto argumenty ''elem1'' a ''elem2''. Potom úplný funkčný prototyp porovnávacej funkcie bude:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
int (*fcmp)(const void *elem1, const void *elem2);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Od funkcie ''fcmp'' sa vyžaduje aby vracala celé číslo v závislosti od výsledku porovnania argumentov ''elem1'' a ''elem2'' nasledovne:&lt;br /&gt;
* ak *''elem1''  &amp;lt;  *''elem2''        potom ''fcmp'' vráti celé číslo &amp;lt; 0&lt;br /&gt;
* ak *''elem1''  == *''elem2''        potom ''fcmp'' vráti 0&lt;br /&gt;
* ak *''elem1''  &amp;gt;  *''elem2''        potom ''fcmp'' vráti celé číslo &amp;gt; 0&lt;br /&gt;
&lt;br /&gt;
Pri porovnávaní elementov elem1 a elem2 symbol &amp;lt; znamená, že elem1 je menší ako elem2 v tom zmysle, že v utriedenom poli sa elem1 nachádza pred elem2. Podobne pre symbol &amp;gt;. Ak sú porovnávané elementy z pohľadu triediaceho kritéria ekvivalenté (symbol ==) potom funkcia vráti nulu. Napríklad ak porovnávame dva reťazce a kritériom je abcedné usporiadanie, potom reťazec &amp;quot;Alexandra&amp;quot; je menší ako reťazec &amp;quot;Zora&amp;quot;. Ak by sme však chceli triediť podľa dĺžky reťazca, potom reťazec &amp;quot;Alexandra&amp;quot; je väčší ako reťazec &amp;quot;Zora&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Triedenie poľa sa potom realizuje volaním funkcie ''qsort'' s patričnými parametrami.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
''Poznámka'': Pri porovnávaní porovnávame obsahy argumentov ''elem1'' a ''elem2'', to znamená, že píšeme napr. *''elem1''  &amp;lt;  *''elem2'' namiesto ''elem1''  &amp;lt; ''elem2''. Zápis ''elem1''  &amp;lt;  ''elem2'' by totiž znamenal, že máme porovnať hodnotu ''elem1'' a ''elem2'' čo by znamenalo, že máme porovnať nejaké adresy uložené v premenných ''elem1'' a ''elem2'' (tieto premenné sú ukazovatele a teda pamätajú adresu, nie samotnú štruktúru). Porovnanie ''elem1''  &amp;lt;  ''elem2'' by teda bolo syntakticky správne, ale nemalo by zmysel. Chceme predsa porovnávať zamestnancov a nie adresy pamäte kde sú títo zamestnanci uložení. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Použitie funkcie ''qsort'' ilustrujeme na nasledujúcom jednoduchom príklade:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#define POCET_PRVKOV 6&lt;br /&gt;
&lt;br /&gt;
int pole[POCET_PRVKOV] = { 45, 11, 100, 30, 20, 27 };&lt;br /&gt;
&lt;br /&gt;
int Porovnaj_cele_cisla (const void * a, const void * b)&lt;br /&gt;
{&lt;br /&gt;
   // Parameter &amp;quot;a&amp;quot; je pointer typu &amp;quot;const void *&amp;quot;. Preto ho pred použitím musíme pretypovať na poiter na &amp;quot;int&amp;quot;. Čiže: &amp;quot;(int *)a&amp;quot;. &lt;br /&gt;
   // Pretože zápis &amp;quot;(int *)a&amp;quot; predstavuje pointer a my chceme porovnávať celé číslo, ktoré je uložené tam kde tento pointer ukazuje&lt;br /&gt;
   // musíme ďalej napísať: &amp;quot;*(int *)a&amp;quot;. Týmto zápisom sa dostaneme k hodnote čísla na ktoré ukazuje predaný parameter &amp;quot;const void * a&amp;quot;.&lt;br /&gt;
   // Podobne pre parameter &amp;quot;b&amp;quot;.&lt;br /&gt;
   return ( *(int*)a - *(int*)b );  &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main ()&lt;br /&gt;
{&lt;br /&gt;
  int n;&lt;br /&gt;
  // Vzostupné utriedenie poľa:&lt;br /&gt;
  qsort (pole, POCET_PRVKOV, sizeof(int), Porovnaj_cele_cisla);&lt;br /&gt;
&lt;br /&gt;
  // Výpis na monitor:&lt;br /&gt;
  for (n=0; n&amp;lt;POCET_PRVKOV; n++)&lt;br /&gt;
     printf (&amp;quot;%d &amp;quot;,values[n]);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Možné riešenie'''&lt;br /&gt;
&lt;br /&gt;
Bude zverejnené neskôr.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Komentár k uvedenému riešeniu'''&lt;br /&gt;
&lt;br /&gt;
Bude zverejnený neskôr.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Nedostatky uvedeného riešenia a námety na zlepšenie'''&lt;br /&gt;
&lt;br /&gt;
Budú zverejnené neskôr.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Triedenie poľa ukazovateľov ''aneb'' Triedime štruktúry efektívne==&lt;br /&gt;
'''Zadanie'''&lt;br /&gt;
&lt;br /&gt;
Uvažujme rovnaké zadanie ako v predošlom. Navyše požadujme viacúrovňové (vnorené) triedenie podľa triediaceho kritéria s nižšou prioritou ak sú položky podľa aktuálneho triediaceho kritéria ekvivalentné. V našom jednoduchom príklade to znamená, že ak napríklad triedime zamestnancov podľa krstného mena a mená niektorých zamestnancov sú rovnaké, potom budú títo utriedení podľa priezviska. Naopak, ak budeme triediť podľa priezviska a priezviská niektorých zamestnancov budú rovnaké, potom ich utriedime podľa krstného mena. Túto situáciu môžeme rozšíriť aj o triedenie podľa roku narodenia. V tomto prípade môžeme definovať prioritu jednotlivým triediacim kritériam a triediť následne podľa priorít.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Metodický komentár'''&lt;br /&gt;
&lt;br /&gt;
:Cieľom tejto úlohy v porovaní s predchádzajúcou je efektívne triediť dáta použitím ukazovateľov a poukázať na ďalšie možnosti pri ich triedení.  Využijú sa pokročilejšie techniky práce s ukazovateľmi, dynamická alokácia a realokácia pamäte. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Vzorové dáta'''&lt;br /&gt;
:Ako v predošlom.&lt;br /&gt;
	&lt;br /&gt;
&lt;br /&gt;
'''Zjednodušujúce predpoklady'''&lt;br /&gt;
&lt;br /&gt;
:Rovnaké ako v predošlom s tým rozdielom, že počet záznamov v súbore nie je obmedzený. Predpokladáme však, že systém má dostatok voľnej pamäte. &lt;br /&gt;
:V súbore sa teda môže nachádzať niekoľko desiatok, ale aj stoviek tisícov záznamov.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Vzorová výzva programu'''&lt;br /&gt;
 Vyber postupnost kriterii triedenia. (Prve kriterium ma najvacsiu prioritu.)&lt;br /&gt;
   Meno, Priezvisko, Rok    1&lt;br /&gt;
   Priezvisko, Meno, Rok    2&lt;br /&gt;
   Rok, Meno, Priezvisko    3&lt;br /&gt;
   Rok, Priezvisko, Meno    4&lt;br /&gt;
   Pre ukoncenie programu   0&lt;br /&gt;
 Volba: _&lt;br /&gt;
&lt;br /&gt;
'''Vzorový vstup'''&lt;br /&gt;
 1	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Vzorový výstup'''&lt;br /&gt;
 --------------------------------------------------------&lt;br /&gt;
  ZAMESTNANEC                               ROK NARODENIA&lt;br /&gt;
 --------------------------------------------------------&lt;br /&gt;
  Alenka               Biela                    1985&lt;br /&gt;
  Alzbetka             Mudra                    1978&lt;br /&gt;
  Andrea               Mlada                    1990&lt;br /&gt;
  Janko                Maly                     1978&lt;br /&gt;
  Janko                Maly                     1983&lt;br /&gt;
  Jozko                Cierny                   1985&lt;br /&gt;
  Martin               Starsi                   1939&lt;br /&gt;
 --------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Návod ako začať'''&lt;br /&gt;
&lt;br /&gt;
Prvým významným rozdielom v porovnaní s predchádzajúcim zadaním je skutočnosť, že počet záznamov (zamestnancov) v súbore nie je obmedzený a je vopred neznámy. Z toho dôvodu je použitie statického poľa štruktúr neefektívne. Riešením je dynamická alokácia pamäte. Mohli by sme tak dynamicky alokovať pole štruktúr podľa aktuálnej potreby programu. Ak sa však zamyslíme nad požiadavkou efektívneho triedenia zamestnancov prichádzame k záveru, že ani toto riešenie by nebolo vhodné. Dôvodom je činnosť funkcie ''qsort'', ktorá pri triedení manipuluje s celými položkami poľa, ktoré by v tomto prípade boli štruktúry (keďže by sa jednalo o pole štruktúr či už staticky alebo dynamicky alokované). Funkcia ''qsort'' by tak musela pracovať pri triedení s pomerne veľkým objemom dát. Riešením tejto situácie je použitie dynamicky alokovaného poľa ukazovateľov. Jednotlivé položky poľa by potom už neboli samotné štruktúry, ale adresy týchto štruktúr. Ako vieme, veľkosť adresy je 4 bajty (resp. 8B v 64-bitovom OS). Takže funkcia ''qsort'' bude triediť pole adries tak aby po zotriedení boli splnené požiadavky triedenia dané prioritami triediacich kritérií. Ak zhrnieme doteraz povedané, tak pre pamätanie celého súboru zamestnancov je výhodné použiť dynamicky alokované pole ukazovateľov, v ktorom pre každý prvok poľa budeme dynamicky alokovať pamäťový priestor pre pamätanie štruktúry uchovávajúcej údaje o jednom konkrétnom zamestnancovi.&lt;br /&gt;
&lt;br /&gt;
Druhým významným rozdielom je požiadavka na viacúrovňové triedenie. Pri písaní porovnávacích funkcií zohľadňujúcich tri úrovne priorít triediacih kritérií je výhodné začať od písania funkcií pre jednoúrovňové triedenie (pozri predchádzajúci príklad), tieto ďalej využiť pri písaní dvojúrovňových, a tieto spolu zasa pri písaní trojúrovňových. Takto môžeme veľmi jednoducho a prehľadne podľa potreby napísať rôzne mnohoúrovňové porovnávacie funkcie.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Možné riešenie'''&lt;br /&gt;
&lt;br /&gt;
Bude zverejnené neskôr.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Komentár k uvedenému riešeniu'''&lt;br /&gt;
&lt;br /&gt;
Bude zverejnený neskôr.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Nedostatky uvedeného riešenia a námety na zlepšenie'''&lt;br /&gt;
&lt;br /&gt;
Budú zverejnené neskôr.&lt;/div&gt;</summary>
		<author><name>Mstepanovsky</name></author>
		
	</entry>
	<entry>
		<id>http://www.kiwiki.info/index.php?title=Triedenie(rie%C5%A1en%C3%A9_pr%C3%ADklady)&amp;diff=2348</id>
		<title>Triedenie(riešené príklady)</title>
		<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php?title=Triedenie(rie%C5%A1en%C3%A9_pr%C3%ADklady)&amp;diff=2348"/>
		<updated>2010-02-23T12:28:03Z</updated>

		<summary type="html">&lt;p&gt;Mstepanovsky: Vytvorená stránka „==Triedenie poľa štruktúr== '''Zadanie'''  Zostavte program, ktorý bude triediť dáta uložené v súbore na základe užívateľom zadaného kritéria. Program po spu…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Triedenie poľa štruktúr==&lt;br /&gt;
'''Zadanie'''&lt;br /&gt;
&lt;br /&gt;
Zostavte program, ktorý bude triediť dáta uložené v súbore na základe užívateľom zadaného kritéria. Program po spustení načíta dáta zo súboru a uloží ich do poľa štruktúr. Následne na monitor zobrazí výzvu, v ktorej bude mať užívateľ možnosť vybrať kritérium triedenia. Pre jednoduchosť uvažujme príklad, v ktorom budeme triediť zamestnancov nejakej fiktívnej firmy podľa mena, priezviska alebo podľa roku jeho narodenia. Dáta v súbore nech sú uložené vo formáte kde jednotlivé položky sú oddelené medzerami čiarkami v tvare:&lt;br /&gt;
 Meno Priezvisko , Rok_narodenia &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
'''Metodický komentár'''&lt;br /&gt;
&lt;br /&gt;
Cieľom tejto úlohy je precvičiť prácu so štruktúrami v jazyku C, použitie funkcie rýchleho triedenia (quick sort) z knižnice ''stdlib.h'', načítavanie dát zo súboru, a pomôcť osvojiť si základné znalosti pri práci s ukazovateľmi (predávanie ako parameter do funkcie, pretypovávanie).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Vzorové dáta'''&lt;br /&gt;
 Janko Maly , 1978&lt;br /&gt;
 Martin Starsi , 1939&lt;br /&gt;
 Andrea Mlada , 1990&lt;br /&gt;
 Jozko Cierny , 1985&lt;br /&gt;
 Alenka Biela , 1985&lt;br /&gt;
 Janko Maly , 1983&lt;br /&gt;
 Alzbetka Mudra , 1978&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
'''Zjednodušujúce predpoklady'''&lt;br /&gt;
&lt;br /&gt;
Dĺžka mena ani priezviska neprekračuje rozsah 20 znakov. V zdrojovom súbore sa nebude nachádzať viac ako 100 záznamov. Zdrojový súbor sa nachádza v tom istom adresáry ako samotný program (*.exe súbor) a jeho názov je: data.txt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Vzorová výzva programu'''&lt;br /&gt;
 Vyber kriterium triedenia.&lt;br /&gt;
   Meno                     1&lt;br /&gt;
   Priezvisko               2&lt;br /&gt;
   Rok narodenia            3&lt;br /&gt;
   Pre ukoncenie programu   0&lt;br /&gt;
 Volba: _&lt;br /&gt;
	&lt;br /&gt;
'''Vzorový vstup'''&lt;br /&gt;
 1	&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
'''Vzorový výstup'''&lt;br /&gt;
 --------------------------------------------------------&lt;br /&gt;
  ZAMESTNANEC                               ROK NARODENIA&lt;br /&gt;
 --------------------------------------------------------&lt;br /&gt;
  Alenka               Biela                    1985&lt;br /&gt;
  Alzbetka             Mudra                    1978&lt;br /&gt;
  Andrea               Mlada                    1990&lt;br /&gt;
  Janko                Maly                     1983&lt;br /&gt;
  Janko                Maly                     1978&lt;br /&gt;
  Jozko                Cierny                   1985&lt;br /&gt;
  Martin               Starsi                   1939&lt;br /&gt;
 --------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Návod ako začať'''&lt;br /&gt;
&lt;br /&gt;
Zo zadania vyplýva, že hlavným účelom programu je triediť (vzostupne príp. zostupne zoradzovať) zamestnancov podľa triediaceho kritéria (meno, priezvisko, rok). Aby sme pri manipulácii (triedení) s jednotlivými zamestnancami pracovali ucelene so všetkými dátami vzťahujúcimi sa ku konkrétnemu zamestnancovi naraz, bude výhodné použiť štruktúru, ktorá nám tieto dáta takpovediac &amp;quot;zabalí&amp;quot;. Takto budeme mať údaje o jednom zamestnancovi pohromade a budeme môcť s nimi pohodlne manipulovať. Týmto sme vyriešili problém ako reprezentovať jedného zamestnanca. Teraz sa vynára otázka ako efektívne pracovať s celým súborom zamestnancov. Pretože vieme, že v zdrojovom súbore sa nebude nachádzať viac ako 100 zamestnancov, bude vcelku výhodné použiť statické pole štruktúr na pamätanie všetkých zamestnancov. Dĺžka tohto poľa bude 100 položiek. Jedna položka poľa potom bude predstavovať jedného konkrétneho zamestnanca. Utriedenie zamestnancov potom budeme realizovať utriedením tohto poľa. Pre triedenie poľa ponúka knižnica ''stdlib.h'' funkciu rýchleho triedenia ''qsort''. Parametre a použitie funkcie ''qsort'' z knižnice ''stdlib.h'' si teraz vysvetlíme.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Úplný funkčný prototyp funkcie ''qsort'' je nasledovný:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void qsort(void *base, size_t nelem, size_t width, int (*fcmp)(const void *, const void *));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Ako vidíme funkcia má štyri parametre, ktorých význam je:&lt;br /&gt;
*''base''  - pointer typu void ukazujúci na nultý element triedeného poľa &lt;br /&gt;
*''nelem'' - počet elementov v triedenom poli&lt;br /&gt;
*''width'' - veľkosť jedného elementu v bajtoch&lt;br /&gt;
*''fcmp''  - pointer na porovnávaciu funkciu, ktorá porovnáva dva elementy triedeného poľa&lt;br /&gt;
&lt;br /&gt;
Porovnávacia funkcia vyžaduje dva argumenty - pointery typu ''const void *''. Označme tieto argumenty ''elem1'' a ''elem2''. Potom úplný funkčný prototyp porovnávacej funkcie bude:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
int (*fcmp)(const void *elem1, const void *elem2);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Od funkcie ''fcmp'' sa vyžaduje aby vracala celé číslo v závislosti od výsledku porovnania argumentov ''elem1'' a ''elem2'' nasledovne:&lt;br /&gt;
* ak *''elem1''  &amp;lt;  *''elem2''        potom ''fcmp'' vráti celé číslo &amp;lt; 0&lt;br /&gt;
* ak *''elem1''  == *''elem2''        potom ''fcmp'' vráti 0&lt;br /&gt;
* ak *''elem1''  &amp;gt;  *''elem2''        potom ''fcmp'' vráti celé číslo &amp;gt; 0&lt;br /&gt;
&lt;br /&gt;
Pri porovnávaní elementov elem1 a elem2 symbol &amp;lt; znamená, že elem1 je menší ako elem2 v tom zmysle, že v utriedenom poli sa elem1 nachádza pred elem2. Podobne pre symbol &amp;gt;. Ak sú porovnávané elementy z pohľadu triediaceho kritéria ekvivalenté (symbol ==) potom funkcia vráti nulu. Napríklad ak porovnávame dva reťazce a kritériom je abcedné usporiadanie, potom reťazec &amp;quot;Alexandra&amp;quot; je menší ako reťazec &amp;quot;Zora&amp;quot;. Ak by sme však chceli triediť podľa dĺžky reťazca, potom reťazec &amp;quot;Alexandra&amp;quot; je väčší ako reťazec &amp;quot;Zora&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Triedenie poľa sa potom realizuje volaním funkcie ''qsort'' s patričnými parametrami.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
''Poznámka'': Pri porovnávaní porovnávame obsahy argumentov ''elem1'' a ''elem2'', to znamená, že píšeme napr. *''elem1''  &amp;lt;  *''elem2'' namiesto ''elem1''  &amp;lt; ''elem2''. zápis ''elem1''  &amp;lt;  ''elem2'' by totiž znamenal, že máme porovnať hodnotu ''elem1'' a ''elem2'' čo by znamenalo, že máme porovnať nejaké adresy uložené v premenných ''elem1'' a ''elem2'' (tieto premenné sú ukazovatele a teda pamätajú adresu, nie samotnú štruktúru). Porovnanie ''elem1''  &amp;lt;  ''elem2'' by teda bolo syntakticky správne, ale nemalo by zmysel. Chceme predsa porovnávať zamestnancov a nie adresy pamäte kde sú títo zamestnanci uložení. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Použitie funkcie ''qsort'' ilustrujme na nasledujúcom jednoduchom príklade:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#define POCET_PRVKOV 6&lt;br /&gt;
&lt;br /&gt;
int pole[POCET_PRVKOV] = { 45, 11, 100, 30, 20, 27 };&lt;br /&gt;
&lt;br /&gt;
int Porovnaj_cele_cisla (const void * a, const void * b)&lt;br /&gt;
{&lt;br /&gt;
   // Parameter &amp;quot;a&amp;quot; je pointer typu &amp;quot;const void *&amp;quot;. Preto ho pred použitím musíme pretypovať na poiter na &amp;quot;int&amp;quot;. Čiže: &amp;quot;(int *)a&amp;quot;. &lt;br /&gt;
   // Pretože zápis &amp;quot;(int *)a&amp;quot; predstavuje pointer a my chceme porovnávať celé číslo, ktoré je uložené tam kde tento pointer ukazuje&lt;br /&gt;
   // musíme ďalej napísať: &amp;quot;*(int *)a&amp;quot;. Týmto zápisom sa dostaneme k hodnote čísla na ktoré ukazuje predaný parameter &amp;quot;const void * a&amp;quot;.&lt;br /&gt;
   // Podobne pre parameter &amp;quot;b&amp;quot;.&lt;br /&gt;
   return ( *(int*)a - *(int*)b );  &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main ()&lt;br /&gt;
{&lt;br /&gt;
  int n;&lt;br /&gt;
  qsort (pole, POCET_PRVKOV, sizeof(int), Porovnaj_cele_cisla);&lt;br /&gt;
  for (n=0; n&amp;lt;POCET_PRVKOV; n++)&lt;br /&gt;
     printf (&amp;quot;%d &amp;quot;,values[n]);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Možné riešenie'''&lt;br /&gt;
&lt;br /&gt;
Bude zverejnené neskôr.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Komentár k uvedenému riešeniu'''&lt;br /&gt;
&lt;br /&gt;
Bude zverejnený neskôr.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Nedostatky uvedeného riešenia a námety na zlepšenie'''&lt;br /&gt;
&lt;br /&gt;
Budú zverejnené neskôr.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Triedenie poľa ukazovateľov ''aneb'' Triedime štruktúry efektívne==&lt;br /&gt;
'''Zadanie'''&lt;br /&gt;
&lt;br /&gt;
Uvažujme rovnaké zadanie ako v predošlom s tým rozdielom, že načítané dáta nebudeme ukladať do poľa štruktúr. Navyše požadujme vnorené triedenie podľa triediaceho kritéria s nižšou prioritou ak sú položky podľa aktuálneho triediaceho kritéria ekvivalentné. V našom jednoduchom príklade to znamená, že ak napríklad triedime zamestnancov podľa krstného mena a mená niektorých zamestnancov sú rovnaké, potom budú títo utriedení podľa priezviska. Naopak, ak budeme triediť podľa priezviska a priezviská niektorých zamestnancov budú rovnaké, potom ich utriedime podľa krstného mena. Túto situáciu môžeme rozšíriť aj o triedenie podľa roku narodenia. V tomto prípade môžeme definovať prioritu jednotlivým triediacim kritériam a triediť následne podľa priorít.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Metodický komentár'''&lt;br /&gt;
&lt;br /&gt;
Cieľom tejto úlohy v porovaní s predchádzajúcou je efektívne triediť dáta použitím ukazovateľov a poukázať na ďalšie možnosti pri ich triedení.  Využijú sa pokročilejšie techniky práce s ukazovateľmi, dynamická alokácia a realokácia pamäte. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Vzorové dáta'''&lt;br /&gt;
  Ako v predošlom.&lt;br /&gt;
	&lt;br /&gt;
&lt;br /&gt;
'''Zjednodušujúce predpoklady'''&lt;br /&gt;
&lt;br /&gt;
  Rovnaké ako v predošlom s tým rozdielom, že počet záznamov v súbore nie je obmedzený. Predpokladáme však, že systém má dostatok voľnej pamäte. V súbore sa teda môže nachádzať niekoľko desiatok, ale aj stoviek tisícov záznamov.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Vzorová výzva programu'''&lt;br /&gt;
 Vyber postupnost kriterii triedenia. (Prve kriterium ma najvacsiu prioritu.)&lt;br /&gt;
   Meno, Priezvisko, Rok    1&lt;br /&gt;
   Priezvisko, Meno, Rok    2&lt;br /&gt;
   Rok, Meno, Priezvisko    3&lt;br /&gt;
   Rok, Priezvisko, Meno    4&lt;br /&gt;
   Pre ukoncenie programu   0&lt;br /&gt;
 Volba: _&lt;br /&gt;
&lt;br /&gt;
'''Vzorový vstup'''&lt;br /&gt;
 1	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Vzorový výstup'''&lt;br /&gt;
 --------------------------------------------------------&lt;br /&gt;
  ZAMESTNANEC                               ROK NARODENIA&lt;br /&gt;
 --------------------------------------------------------&lt;br /&gt;
  Alenka               Biela                    1985&lt;br /&gt;
  Alzbetka             Mudra                    1978&lt;br /&gt;
  Andrea               Mlada                    1990&lt;br /&gt;
  Janko                Maly                     1978&lt;br /&gt;
  Janko                Maly                     1983&lt;br /&gt;
  Jozko                Cierny                   1985&lt;br /&gt;
  Martin               Starsi                   1939&lt;br /&gt;
 --------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Návod ako začať'''&lt;br /&gt;
&lt;br /&gt;
Prvým významným rozdielom v porovnaní s predchádzajúcim zadaním je skutočnosť, že počet záznamov (zamestnancov) v súbore nie je obmedzený a je vopred neznámy. Z toho dôvodu je použitie statického poľa štruktúr neefektívne. Riešením je dynamická alokácia pamäte. Mohli by sme tak dynamicky alokovať pole štruktúr podľa aktuálnej potreby programu. Ak sa však zamyslíme nad požiadavkou efektívneho triedenia zamestnancov prichádzame k záveru, že ani toto riešenie by nebolo vhodné. Dôvodom je činnosť funkcie ''qsort'', ktorá pri triedení manipuluje s celými položkami poľa, ktoré by v tomto prípade boli štruktúry (keďže by sa jednalo o pole štruktúr či už staticky alebo dynamicky alokované). Funkcia ''qsort'' by tak musela pracovať pri triedení s pomerne veľkým objemom dát. Riešením tejto situácie je použitie dynamicky alokovaného poľa ukazovateľov. Jednotlivé položky poľa by potom už neboli samotné štruktúry, ale adresy týchto štruktúr. Ako vieme, veľkosť adresy je 4 bajty (resp. 8B v 64-bitovom OS). Takže funkcia ''qsort'' bude triediť pole adries tak aby po zotriedení boli splnené požiadavky triedenia dané prioritami triediacich kritérií.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Možné riešenie'''&lt;br /&gt;
&lt;br /&gt;
Bude zverejnené neskôr.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Komentár k uvedenému riešeniu'''&lt;br /&gt;
&lt;br /&gt;
Bude zverejnený neskôr.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Nedostatky uvedeného riešenia a námety na zlepšenie'''&lt;br /&gt;
&lt;br /&gt;
Budú zverejnené neskôr.&lt;/div&gt;</summary>
		<author><name>Mstepanovsky</name></author>
		
	</entry>
	<entry>
		<id>http://www.kiwiki.info/index.php?title=Rekurzia_(rie%C5%A1en%C3%A9_pr%C3%ADklady)&amp;diff=2347</id>
		<title>Rekurzia (riešené príklady)</title>
		<link rel="alternate" type="text/html" href="http://www.kiwiki.info/index.php?title=Rekurzia_(rie%C5%A1en%C3%A9_pr%C3%ADklady)&amp;diff=2347"/>
		<updated>2010-02-23T10:47:09Z</updated>

		<summary type="html">&lt;p&gt;Mstepanovsky: /* Prevod čísel z 10-vej sústavy */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Kategória:Študijné materiály]]&lt;br /&gt;
[[Kategória:Programovanie]]&lt;br /&gt;
[[Kategória:jazyk C]]&lt;br /&gt;
{{Draft}}&lt;br /&gt;
{{Skripta programovanie (zbierka úloh)}}&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Prevod čísel z 10-vej sústavy==&lt;br /&gt;
'''Zadanie'''&lt;br /&gt;
&lt;br /&gt;
Zostavte program, ktorý bude prevádzať prirodzené čísla do ľubovoľných číselných sústav so základom Z&amp;lt;10, využitím rekurzívnej funkcie. Túto funkciu postupne zdokonaľujte:&lt;br /&gt;
#Funkciu vylepšite, aby vedela prevádzať aj do sústav so základom Z&amp;lt;=16.&lt;br /&gt;
#Upravte funkciu tak, aby vedela prevádzať všetky celé čísla (čiže aj záporné a nulu).&lt;br /&gt;
#Pokúste sa funkciu obohatiť o prevod reálnych čísel (čiže aj desatinných).&lt;br /&gt;
V programe načítajte 2 vstupné údaje: číslo N v 10-vej sústave a základ novej sústavy z.&lt;br /&gt;
&lt;br /&gt;
'''Vzorové príklady'''&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
!vstup&lt;br /&gt;
!&lt;br /&gt;
!výstup&lt;br /&gt;
|-&lt;br /&gt;
|80 2 &lt;br /&gt;
| -&amp;gt;&lt;br /&gt;
|1010000&lt;br /&gt;
|-&lt;br /&gt;
|93 16&lt;br /&gt;
| -&amp;gt;&lt;br /&gt;
|5D&lt;br /&gt;
|-&lt;br /&gt;
|0 8&lt;br /&gt;
| -&amp;gt;&lt;br /&gt;
|0 &lt;br /&gt;
|-&lt;br /&gt;
| -74 4&lt;br /&gt;
| -&amp;gt;&lt;br /&gt;
| -1022&lt;br /&gt;
|-&lt;br /&gt;
|3.141592654 16&lt;br /&gt;
| -&amp;gt;&lt;br /&gt;
|3.243F6A8A48AA&lt;br /&gt;
|-&lt;br /&gt;
| -0.1 2&lt;br /&gt;
| -&amp;gt;&lt;br /&gt;
| -0.0001100110011001100&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Je vhodné začať jednoduchou funkciou na prevod prirodzeného čísla. Ak máme základ cieľovej sústavy z&amp;lt;10, môžeme problém vyjadriť aj rekurentným vzťahom v matematickom tvare: P(n, z) = P(n/z, z) * 10 + n%z (pre n &amp;gt; 0), a teda by bolo možné vytvoriť funkciu, ktorej návratovou hodnotou by bolo celé číslo.&lt;br /&gt;
&lt;br /&gt;
V prípade, že uvažujeme o vyššom základe, vo výsledku sa objavia aj symboly A, B, C, ...  funkcia by už musela výsledok vracať vo forme reťazca. Pre zjednodušenie nám stačí funkcia, ktorá bude výsledok priamo vypisovať. Je treba si uvedomiť, ako sa počíta prevod čísla – číslo vydelíme základom sústavy, tento podiel prevedieme a za ním bude nasledovať zvyšok po pôvodnom delení.&lt;br /&gt;
&lt;br /&gt;
Na vypísanie zvyšku pre vyššie sústavy by sme mohli pre zvyšky väčšie ako 9 použiť aj inkrementáciu znakového typu: &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
cout &amp;lt;&amp;lt; char (‘A’ + n%z – 10);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Keďže základ sústavy sa počas celého prevodu samozrejme nemení, nemá význam v každom volaní funkcie vytvárať jeho kópiu v podobe vstupnej premennej, ale stačí nám referencia (ušetrí sa pár bajtíkov pri každom vnorení).&lt;br /&gt;
&lt;br /&gt;
Ak chceme, aby funkcia dokázala prevádzať aj nulu a záporné čísla, musíme si pridať akúsi „úvodnú“ funkciu, ktorá ošetrí problematické situácie a až potom zavolá hlavnú rekurzívnu funkciu prevodu.&lt;br /&gt;
&lt;br /&gt;
'''Možné riešenie:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;iostream.h&amp;gt;&lt;br /&gt;
#include &amp;lt;conio.h&amp;gt;&lt;br /&gt;
const char znaky[] = &amp;quot;0123456789ABCDEF&amp;quot;;&lt;br /&gt;
void PrevodCele(int n, int &amp;amp;zaklad)&lt;br /&gt;
{&lt;br /&gt;
   if (n == 0) return;&lt;br /&gt;
   PrevodCele(n/zaklad, zaklad); // prevedie celu cast podielu&lt;br /&gt;
   cout &amp;lt;&amp;lt; znaky[n%zaklad]; // za tym napise zvysok&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void PrevodReal(double r, int &amp;amp;zaklad, int presnost)&lt;br /&gt;
{&lt;br /&gt;
   if (r == 0) return;&lt;br /&gt;
   r *= zaklad; // posunie o jeden rad vlavo&lt;br /&gt;
   cout &amp;lt;&amp;lt; znaky[int(r)]; // celu cast vypise&lt;br /&gt;
   PrevodReal(r - int(r), zaklad, presnost - 1); // zvysok prevedie&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// uvodna funkcia na specialne pripady&lt;br /&gt;
void Prevod(double r, int zaklad, int presnost)&lt;br /&gt;
{&lt;br /&gt;
   // ak je zaporne&lt;br /&gt;
   if (r &amp;lt; 0)&lt;br /&gt;
   {&lt;br /&gt;
      r = -r; cout &amp;lt;&amp;lt; '-';&lt;br /&gt;
   }&lt;br /&gt;
   // cela cast&lt;br /&gt;
   int n = int(r);&lt;br /&gt;
   if (n) &lt;br /&gt;
      PrevodCele(n, zaklad);&lt;br /&gt;
   else &lt;br /&gt;
      cout &amp;lt;&amp;lt; 0; // ak je nula, vypise ju&lt;br /&gt;
&lt;br /&gt;
   // desatinna cast (ak je)&lt;br /&gt;
   if (r -= n)&lt;br /&gt;
   {&lt;br /&gt;
      cout &amp;lt;&amp;lt; '.';&lt;br /&gt;
      PrevodReal(r, zaklad, presnost);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   double r;&lt;br /&gt;
   int sustava;&lt;br /&gt;
   cout &amp;lt;&amp;lt; &amp;quot;cislo v 10-kovej sustave: &amp;quot;; cin &amp;gt;&amp;gt; r;&lt;br /&gt;
   cout &amp;lt;&amp;lt; &amp;quot;cielova sustava: &amp;quot;; cin &amp;gt;&amp;gt; sustava;&lt;br /&gt;
   cout &amp;lt;&amp;lt; &amp;quot;prevedene: &amp;quot;;&lt;br /&gt;
   Prevod(r, sustava, 6);&lt;br /&gt;
   getch();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Prvočísla==&lt;br /&gt;
&lt;br /&gt;
'''Zadanie:'''&lt;br /&gt;
&lt;br /&gt;
Pomocou rekurzívneho riešenia vytvorte funkciu, ktorá otestuje, či je dané číslo prvočíslo.&lt;br /&gt;
===Prvé riešenie - neoptimalizované===&lt;br /&gt;
&lt;br /&gt;
'''Analýza riešenia:'''&lt;br /&gt;
&lt;br /&gt;
Testujeme číslo n na prvočíselnosť. Číslo n budeme postupne deliť číslami od 2 až po (n-1) aby sme zistili zvyšok po delení. Pri prvom zvyšku, ktorý je rovný 0 (teda číslo z delí číslo n bezo zvyšku) funkciu ukončíme a vrátime hodnotu 0 (n nie je prvočíslo). Ak je z&amp;lt;(n-1) tak funkciu is_prime1 voláme rekurzívne a v tomto volaní zvýšime parameter z o 1. (riadok č. 8). V prípade, že neplatí rovnosť z&amp;lt;(n-1) a ani jedno číslo z intervalu &amp;lt;2,n-1&amp;gt; nedelí číslo n bezo zvyšku, vrátime hodnotu 1 (n je prvočíslo).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Možné riešenie:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot; line &amp;gt;&lt;br /&gt;
int is_prime1(int n, int z=2)&lt;br /&gt;
{  &lt;br /&gt;
   if((n%z)==0)&lt;br /&gt;
      return 0;&lt;br /&gt;
   else&lt;br /&gt;
   {&lt;br /&gt;
      if(z&amp;lt;(n-1))&lt;br /&gt;
         return is_prime1(n,z+1);&lt;br /&gt;
      else&lt;br /&gt;
         return 1;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
===Druhé riešenie - čiastočne optimalizované===&lt;br /&gt;
Optimalizácia v tomto prípade znamená eliminovať počet delení modulo. Myšlienka nájdenia hornej hranice hodnoty premennej ''z'' z predchádzajúceho príkladu:&lt;br /&gt;
*Číslo n delíme modulo hodnotou 2. (výsledok je rôzny od 0)&lt;br /&gt;
** nemá zmysel deliť číslom ''z'' väčším ako je n/2, pretože už nám nemôže vyjsť celočíselný podiel. Výsledok takéhoto delenia bude v intervale (0,1)&lt;br /&gt;
*Číslo n delíme modulo hodnotou 3. (výsledok je rôzny od 0)&lt;br /&gt;
** nemá zmysel deliť číslom ''z'' väčším ako je n/3, pretože už nám nemôže vyjsť celočíselný podiel. Výsledok takéhoto delenia bude v intervale &amp;lt;math&amp;gt;(1,2) \cup (2,3)&amp;lt;/math&amp;gt;. Podiel nebude mať hodnotu 2, pretože v tom prípade by bolo číslo n delitelné číslom 3 bezo zvyšku.&lt;br /&gt;
*Delitel n budeme zväčšovať až pokiaľ platí &amp;lt;math&amp;gt;\frac {n}{d}&amp;gt;d&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Horná hranica hodnoty d sa dá určiť nasledovne: &amp;lt;math&amp;gt;d=\sqrt{n}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Možné riešenie:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot; line &amp;gt;&lt;br /&gt;
int is_prime2(int n, int z=2)&lt;br /&gt;
{  &lt;br /&gt;
   if((n%z)==0)&lt;br /&gt;
      return 0;&lt;br /&gt;
   else&lt;br /&gt;
   {&lt;br /&gt;
      if(z&amp;lt;sqrt(n))&lt;br /&gt;
         return is_prime2(n,z+1);&lt;br /&gt;
      else&lt;br /&gt;
         return 1;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Tretie riešenie - viac optimalizované===&lt;br /&gt;
V predchádzajúcom príklade sme delili číslo n hodnotami premennej d. Premenná d mala prvú hodnotu 2 a potom sa k nej vždy pripočítala hodnota 1. Teda, číslo n sme postupne delili hodnotami &lt;br /&gt;
 2, 3, 4, 5, 6, 7, 8, ... &amp;lt;math&amp;gt;d=\sqrt{n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Všimnime si, že niektoré delenia sú opäť zbytočné: &lt;br /&gt;
*ak delíme číslom 2, potom nemá zmysel deliť žiadnym jeho násobkom&lt;br /&gt;
*vo všeobecnosti platí: ak delíme číslom ''j'', potom nemá zmysel deliť žiadnym násobkom čísla ''j''.&lt;br /&gt;
&lt;br /&gt;
Inak povedané, netreba deliť žiadnom zloženým číslom. Stačí deliť prvočíslami. A tu sa dostávame k rekurzívnej definícii prvočísel:&lt;br /&gt;
&lt;br /&gt;
'''Rekurzívna definícia prvočísla''':&lt;br /&gt;
* Číslo 2 je najmenšie prvočíslo.&lt;br /&gt;
* Prvočíslo je každé celé kladné číslo, ktoré nie je deliteľné žiadnym iným menším prvočíslom ako je toto číslo samotné.&lt;br /&gt;
&lt;br /&gt;
Pri takto stanovenej podmienke je komplikovanejšie vytvoriť podmienku, ktoré by toto spĺňala. Preto skúsme napísať program, ktorý by zbytočne nedelil násobkami čísel 2 a 3.&lt;br /&gt;
Ak nechceme deliť násobkami čísla 2, tak potom budeme postupne deliť premennú n hodnotami 3,5,7,9,11,...&lt;br /&gt;
&lt;br /&gt;
Ak nechceme deliť násobkami čísla 3, tak potom budeme postupne deliť premennú n hodnotami 4,5,7,8,10,11,13,14,...&lt;br /&gt;
&lt;br /&gt;
Prienikom týchto dvoch podmienok je, že nám zostava deliť číslami 5,7,10,13,17,19, ...&lt;br /&gt;
&lt;br /&gt;
V tejto postupnosti je jednoduché pravidlo: striedavé pripočítavanie hodnoty 2 a 4. Vyjadrené aritmetickou postupnosťou:&lt;br /&gt;
*&amp;lt;math&amp;gt;d_0=2&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;d_1=3&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;d_2=5&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;d_n=d_{n-1} + 3-(-1)^{i+1}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Možné riešenie:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot; line &amp;gt;&lt;br /&gt;
int is_prime3(int n, int z,int krok)&lt;br /&gt;
{ &lt;br /&gt;
   int d=z+3+krok;&lt;br /&gt;
   if((n%d)==0)&lt;br /&gt;
      return 0;&lt;br /&gt;
   else&lt;br /&gt;
   {&lt;br /&gt;
      if(d&amp;lt;sqrt(n))&lt;br /&gt;
         return is_prime3(n,d,-krok);&lt;br /&gt;
      else&lt;br /&gt;
         return 1;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int is_prime(int n)&lt;br /&gt;
{&lt;br /&gt;
   if((n%2)==0) return 0;&lt;br /&gt;
   if((n%3)==0) return 0;&lt;br /&gt;
   if((n%5)==0) return 0;&lt;br /&gt;
   return is_prime3(n,5,-1);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Rozbor zdrojového kódu:'''&lt;br /&gt;
&lt;br /&gt;
Pre hľadanie prvočísel použijeme funkciu is_prime, ktorá otestuje číslo n na deliteľnosť číslami 2, 3 a 5. Potom zavoláme pomocnú rekurzívnu funkciu is_prime3(int n, int z,int krok) ktorá bude testovať deliteľnosť čísla n prvkami postupnosti &amp;lt;math&amp;gt;\big\{d_n\big\}&amp;lt;/math&amp;gt;. Aby sme sa vyhli zbyto4n7m podmienkam, ktoré môžu celý algoritmus spomaliť, definujeme tretí parameter funkcie is_prime3 ''krok''. Parameter krok je v našej postupnosti výraz &amp;lt;math&amp;gt; 3-(-1)^{i+1}&amp;lt;/math&amp;gt;, avšak tu nepočítame hodnotu mocniny &amp;lt;math&amp;gt;(-1)^{i+1}&amp;lt;/math&amp;gt; ale využívame skutočnosť že tento výraz nadobúda hodnoty -1,1,-1,1, ... .&lt;br /&gt;
&lt;br /&gt;
V premennej d je vypočítaná hodnota aktuálneho deliteľa podľa vzťahu: &amp;lt;math&amp;gt;d_n=d_{n-1} + 3-(-1)^{i+1}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Riešenie s globálnym poľom===&lt;br /&gt;
Pre zjednodušenie tvorby programu si vytvorme globálne pole do ktorého uložíme prvých n prvočísel. Potom najväčšie číslo, ktoré môžeme testovať na prvočíselnosť je &amp;lt;math&amp;gt;N=n^2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Analýza riešenia:'''&lt;br /&gt;
&lt;br /&gt;
Testujeme číslo n na prvočíselnosť. Ako prvé vypočítame zvyšok po delení prvým prvočíslom v poli ''pcisla'' (delíme číslom pcisla[0]=2). V prípade, ak je výsledok 0, tak výpočet ukončíme a vrátime hodnotu (0 - nie je prvočíslo). V opačnom prípade rekurzívne zavoláme funkciu jePrvocislo, kde druhý parameter (má význam indexu v poli ''pcisla'') zvýšime o 1. Teda v ďalšom volaní funkcie jePrvocislo už budeme deliť číslom pcisla[1]=3. Musíme však zabezpečiť, aby hodnota pcisla[i] v riadku č. 5 existovala. To zabezpečíme tak, že rekurzívne volanie dovolíme len ak je hodnota indexu i menšia ako počet hodnôt v pole pcisla.&lt;br /&gt;
&lt;br /&gt;
'''Možné riešenie:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot; line &amp;gt;&lt;br /&gt;
int prvocisla[]={2,3,5,7,11,13,17,19,23,29,31,37};&lt;br /&gt;
&lt;br /&gt;
int is_prime4(int n, int i=0)&lt;br /&gt;
{ &lt;br /&gt;
  if(n%prvocisla[i]==0)&lt;br /&gt;
     return 0;&lt;br /&gt;
  if(i&amp;lt;223 &amp;amp;&amp;amp; n&amp;gt;pow(prvocisla[i],2))&lt;br /&gt;
     return is_prime4(n,i+1);&lt;br /&gt;
  else &lt;br /&gt;
     return 1;   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Vzorové riešenie'''&lt;br /&gt;
&lt;br /&gt;
Uvádzame postupnosť volaní funkcie '''is_prime4(31)'''&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
|+&lt;br /&gt;
!Vnorenie&lt;br /&gt;
!Volaná funkcia&lt;br /&gt;
!prvocisla[i]&lt;br /&gt;
!n%prvocisla[i]&lt;br /&gt;
!rekurzívne volanie&lt;br /&gt;
|-&lt;br /&gt;
|0&lt;br /&gt;
|is_prime(31,0)&lt;br /&gt;
|2&lt;br /&gt;
|31%2=1&lt;br /&gt;
|is_prime(31,1)&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|is_prime(31,1)&lt;br /&gt;
|3&lt;br /&gt;
|31%3=1&lt;br /&gt;
|is_prime(31,2)&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|is_prime(31,2)&lt;br /&gt;
|5&lt;br /&gt;
|31%5=1&lt;br /&gt;
|is_prime(31,3)&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|is_prime(31,3)&lt;br /&gt;
|7&lt;br /&gt;
|31%7=3&lt;br /&gt;
|is_prime(31,4)&lt;br /&gt;
|-&lt;br /&gt;
| 4&lt;br /&gt;
| is_prime(31,4)&lt;br /&gt;
| 11&lt;br /&gt;
| n.a.&lt;br /&gt;
| neplatí podmienka n&amp;gt;prvocisla[i]^2&amp;lt;br/&amp;gt;n=31, i=4, prvocisla[i]=11&amp;lt;br/&amp;gt;funkcia vracia hodnotu '''1'''&lt;br /&gt;
|-&lt;br /&gt;
| 3&lt;br /&gt;
| návrat na is_prime(31,3)&lt;br /&gt;
| 7&lt;br /&gt;
| n.a.&lt;br /&gt;
| spätný rekurzívny chod&lt;br /&gt;
|-&lt;br /&gt;
| 2&lt;br /&gt;
| návrat na is_prime(31,2)&lt;br /&gt;
| 5&lt;br /&gt;
| n.a.&lt;br /&gt;
| spätný rekurzívny chod&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| návrat na is_prime(31,1)&lt;br /&gt;
| 3&lt;br /&gt;
| n.a.&lt;br /&gt;
| spätný rekurzívny chod&lt;br /&gt;
|-&lt;br /&gt;
| 0&lt;br /&gt;
| návrat na is_prime(31,0)&lt;br /&gt;
| 2&lt;br /&gt;
| n.a.&lt;br /&gt;
| spätný rekurzívny chod&lt;br /&gt;
|}&lt;br /&gt;
====Porovnanie efektivity navrhovaných algoritmov====&lt;br /&gt;
Skôr ako budeme porovnávať ukázané algoritmy, poznamenajme, že tento spôsob zisťovania prvočíselnosti je pre veľké čísla veľmi neefektívny. Pri 8-cifernom čísle trvá výpočet funkcie is_prime približne 230 s. Pre zisťovanie prvočíselnosti existujú špeciálne algoritmy, napr. [http://en.wikipedia.org/wiki/AKS_primality_test ASK test], [http://en.wikipedia.org/wiki/Solovay%E2%80%93Strassen_primality_test Test Solovay-Strassena], [http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test Test Millera-Rabina] a iné.&lt;br /&gt;
V nasledujúcej tabuľke a na obrázku sú výsledky porovnania efektívnosti týchto algoritmov pri hľadaní prvočísel na intervale (100,n) kde n sme menili od 50 000 do 2 000 000. V tabuľke ani v grafe nie je zahrnutá funkcia is_prime1, pretože pri n=100 000 pri rekurzívnom volaní funkcia neočakávane skončila.&lt;br /&gt;
Aby sme mohli porovnávať aj funkciu is_prime4, musíme do poľa ''prvocisla'' pridať všetky prvočísla, ktoré sú menšie ako &amp;lt;math&amp;gt;\sqrt{n_{max}}&amp;lt;/math&amp;gt;, kde n_max je v našom prípade 2 000 000. Pole ''prvocisla'' obsahuje prvých 233 prvočísel:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
int prvocisla[]={&lt;br /&gt;
2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,&lt;br /&gt;
191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,&lt;br /&gt;
397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,&lt;br /&gt;
617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,&lt;br /&gt;
857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997,1009,1013,1019,1021,1031,1033,1039,1049,1051,1061,1063,&lt;br /&gt;
1069,1087,1091,1093,1097,1103,1109,1117,1123,1129,1151,1153,1163,1171,1181,1187,1193,1201,1213,1217,1223,1229,1231,1237,1249,1259,1277,1279,&lt;br /&gt;
1283,1289,1291,1297,1301,1303,1307,1319,1321,1327,1361,1367,1373,1381,1399,1409,1423};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Naprogramované funkcie sme testovali nasledovne:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;iostream.h&amp;gt;&lt;br /&gt;
#include &amp;lt;time.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
   clock_t start, end;&lt;br /&gt;
   double elapsed;&lt;br /&gt;
   int n;&lt;br /&gt;
   n=50000; //100000, 200000, ... 2000000&lt;br /&gt;
   start = clock();&lt;br /&gt;
   for(int i=100;i&amp;lt;n;i++)&lt;br /&gt;
      is_prime(i);   &lt;br /&gt;
   end = clock();&lt;br /&gt;
   elapsed = ((double) (end - start)) / CLOCKS_PER_SEC;&lt;br /&gt;
   cout&amp;lt;&amp;lt;elapsed&amp;lt;&amp;lt;endl;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{| class=datatable&lt;br /&gt;
|+Tabuľka nameraných časov behu funkcií&lt;br /&gt;
|-&lt;br /&gt;
!n [tisíc]	&lt;br /&gt;
!is_prime_2 t[s]	&lt;br /&gt;
!is_prime t[s]&lt;br /&gt;
!is_prime4 t[s]&lt;br /&gt;
|-&lt;br /&gt;
|50	&lt;br /&gt;
|0,16	&lt;br /&gt;
|0,086&lt;br /&gt;
|0,061&lt;br /&gt;
|-&lt;br /&gt;
|100	&lt;br /&gt;
|0,398	&lt;br /&gt;
|0,134&lt;br /&gt;
|0,126&lt;br /&gt;
|-&lt;br /&gt;
|200	&lt;br /&gt;
|1,034	&lt;br /&gt;
|0,345&lt;br /&gt;
|0,304&lt;br /&gt;
|-&lt;br /&gt;
|500	&lt;br /&gt;
|1,245	&lt;br /&gt;
|1,237&lt;br /&gt;
|0,958&lt;br /&gt;
|-&lt;br /&gt;
|1000	&lt;br /&gt;
|3,275	&lt;br /&gt;
|3,264&lt;br /&gt;
|2,349&lt;br /&gt;
|-&lt;br /&gt;
|1500	&lt;br /&gt;
|17,203	&lt;br /&gt;
|5,831&lt;br /&gt;
|3,9&lt;br /&gt;
|-&lt;br /&gt;
|2000	&lt;br /&gt;
|26	&lt;br /&gt;
|8,6&lt;br /&gt;
|5,82&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pLines ymin=0 ymax=27 colors=FF0000,00FF00,0000FF size=600x250 plots legend&amp;gt;&lt;br /&gt;
,is_prime2, is_prime, is_prime4&lt;br /&gt;
50 tis, 0.16, 0.08, 0.061&lt;br /&gt;
100 tis, 0.398, 0.134, 0.126&lt;br /&gt;
200 tis, 1.034, 0.345, 0.304&lt;br /&gt;
500 tis, 1.245, 1.237, 0.958&lt;br /&gt;
1 mil, 3.275, 3.264, 2.349&lt;br /&gt;
1.5 mil, 17.203, 5.831, 3.9&lt;br /&gt;
2 mil, 26, 8.6, 5.82&lt;br /&gt;
&amp;lt;/pLines&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Podobné časy pri nižších hodnotách n sú dané tým, že vzdialenosť susedných prvočísel je väčšia pri vyšších prvočíslach. Z grafu taktiež vidieť účinok optimalizácie algoritmu.&lt;br /&gt;
&lt;br /&gt;
==Odkazy==&lt;br /&gt;
*http://sk.wikipedia.org/wiki/Zoznam_prvo%C4%8D%C3%ADsiel&lt;br /&gt;
*http://www.prime-numbers.org/&lt;/div&gt;</summary>
		<author><name>Mstepanovsky</name></author>
		
	</entry>
</feed>