Qsort (jazyk C): Rozdiel medzi revíziami

Z Kiwiki
Skočit na navigaci Skočit na vyhledávání
 
(Jedna medziľahlá úprava od jedného ďalšieho používateľa nie je zobrazená)
Riadok 1: Riadok 1:
 
{{Funkcie jazyka c}}
 
{{Funkcie jazyka c}}
 +
__NOTOC__
 
==Funkcia qsort==
 
==Funkcia qsort==
 
<properties>
 
<properties>
knižnica=stdlib.h
+
knižnica=stdlib.h  
 
popis=Funkcia implementuje algoritmus vyhľadávania Quick sort.
 
popis=Funkcia implementuje algoritmus vyhľadávania Quick sort.
 
</properties>
 
</properties>
  
Úplný funkčný prototyp funkcie ''qsort'' je nasledovný:
+
Úplný funkčný prototyp:
 
<source lang="c">
 
<source lang="c">
void qsort(void *base, size_t nelem, size_t width, int (*fcmp)(const void *, const void *));
+
  void qsort(void *base, size_t nelem, size_t width, int (*fcmp)(const void *, const void *))
 
</source>
 
</source>
Ako vidíme funkcia má štyri parametre, ktorých význam je:
 
*''base''  - ukazovateľ typu void ukazujúci na nultý element triedeného poľa
 
*''nelem'' - počet elementov v triedenom poli
 
*''width'' - veľkosť jedného elementu v bajtoch
 
*''fcmp''  - ukazovateľ na porovnávaciu funkciu, ktorá porovnáva dva elementy triedeného poľa
 
  
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:
+
==Podrobný popis funkcie==
 +
Funkcia vytriedi pole s použitím algoritmu Quick sort.
 +
 
 +
==Parametre==
 +
;''base'':  ukazovateľ typu ''void'' ukazujúci na nultý element triedeného poľa
 +
;''nelem'':  počet elementov v triedenom poli
 +
;''width'':  veľkosť jedného elementu v bajtoch
 +
;''fcmp'':  [[Jazyk C - smerník (pointer)|ukazovateľ]] na porovnávaciu funkciu, ktorá porovnáva dva elementy triedeného poľa
 +
 
 +
 
 +
Porovnávacia funkcia ''fcmp'' vyžaduje dva argumenty - ukazovatele typu ''const void *''. Označme tieto argumenty ''elem1'' a ''elem2''. Potom úplný funkčný prototyp porovnávacej funkcie bude:
 
<source lang="c">
 
<source lang="c">
 
int (*fcmp)(const void *elem1, const void *elem2);
 
int (*fcmp)(const void *elem1, const void *elem2);
 
</source>
 
</source>
  
 +
''Poznámka'': Pri porovnávaní porovnávame obsahy argumentov ''elem1'' a ''elem2'', to znamená, že píšeme napr. *''elem1''  <  *''elem2'' namiesto ''elem1''  < ''elem2''. Zápis ''elem1''  <  ''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''  <  ''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í.
 +
 +
==Návratová hodnota==
 
Od funkcie ''fcmp'' sa vyžaduje aby vracala celé číslo v závislosti od výsledku porovnania argumentov ''elem1'' a ''elem2'' nasledovne:
 
Od funkcie ''fcmp'' sa vyžaduje aby vracala celé číslo v závislosti od výsledku porovnania argumentov ''elem1'' a ''elem2'' nasledovne:
 
* ak *''elem1''  <  *''elem2''        potom ''fcmp'' vráti celé číslo < 0
 
* ak *''elem1''  <  *''elem2''        potom ''fcmp'' vráti celé číslo < 0
Riadok 26: Riadok 35:
 
* ak *''elem1''  >  *''elem2''        potom ''fcmp'' vráti celé číslo > 0
 
* ak *''elem1''  >  *''elem2''        potom ''fcmp'' vráti celé číslo > 0
  
Pri porovnávaní elementov elem1 a elem2 symbol < znamená, že elem1 je menší ako elem2 v tom zmysle, že v utriedenom poli sa elem1 nachádza pred elem2. Podobne pre symbol >. 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 "Alexandra" je menší ako reťazec "Zora". Ak by sme však chceli triediť podľa dĺžky reťazca, potom reťazec "Alexandra" je väčší ako reťazec "Zora".  
+
Pri porovnávaní elementov elem1 a elem2 symbol < znamená, že elem1 je menší ako elem2 v tom zmysle, že v utriedenom poli sa elem1 nachádza pred elem2. Podobne pre symbol >. 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 "Alexandra" je menší ako reťazec "Zora". Ak by sme však chceli triediť podľa dĺžky reťazca, potom reťazec "Alexandra" je väčší ako reťazec "Zora".
  
 
Triedenie poľa sa potom realizuje volaním funkcie ''qsort'' s patričnými parametrami.
 
Triedenie poľa sa potom realizuje volaním funkcie ''qsort'' s patričnými parametrami.
  
 
+
==Príklad==
''Poznámka'': Pri porovnávaní porovnávame obsahy argumentov ''elem1'' a ''elem2'', to znamená, že píšeme napr. *''elem1''  <  *''elem2'' namiesto ''elem1''  < ''elem2''. Zápis ''elem1''  <  ''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''  <  ''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í.
 
 
 
 
 
 
Použitie funkcie ''qsort'' ilustrujeme na nasledujúcom jednoduchom príklade:
 
Použitie funkcie ''qsort'' ilustrujeme na nasledujúcom jednoduchom príklade:
 
<source lang="c">
 
<source lang="c">

Aktuálna revízia z 20:52, 12. máj 2020

Rozdelenie funkcií jazyka C podľa knižníc, v ktorých sú definované
<ctype.h> <limits.h> <stdio.h> <stdlib.h> <math.h> <string.h> <time.h>

isalnum
isalpha
isdigit
isgraph
islower
isprint
ispunct
isspace
isupper
isxdigit

printf
scanf
getc
putc
getchar
putchar
fprintf
fscanf
fgetc
fputc
fopen
fclose
feof

system
malloc
qsort
rand
srand
atoi
atol
atof
itoa
div
abs
labs

pow
fabs
exp
log
log10
sqrt
ceil
sin
cos

strlen
strcmp
strchr
strcpy
strstr
strcat
strncat

clock
time

Funkcia qsort

knižnica

stdlib.h

popis

Funkcia implementuje algoritmus vyhľadávania Quick sort.


Úplný funkčný prototyp:

  void qsort(void *base, size_t nelem, size_t width, int (*fcmp)(const void *, const void *))

Podrobný popis funkcie

Funkcia vytriedi pole s použitím algoritmu Quick sort.

Parametre

base
ukazovateľ typu void ukazujúci na nultý element triedeného poľa
nelem
počet elementov v triedenom poli
width
veľkosť jedného elementu v bajtoch
fcmp
ukazovateľ na porovnávaciu funkciu, ktorá porovnáva dva elementy triedeného poľa


Porovnávacia funkcia fcmp vyžaduje dva argumenty - ukazovatele typu const void *. Označme tieto argumenty elem1 a elem2. Potom úplný funkčný prototyp porovnávacej funkcie bude:

int (*fcmp)(const void *elem1, const void *elem2);

Poznámka: Pri porovnávaní porovnávame obsahy argumentov elem1 a elem2, to znamená, že píšeme napr. *elem1 < *elem2 namiesto elem1 < elem2. Zápis elem1 < 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 < 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í.

Návratová hodnota

Od funkcie fcmp sa vyžaduje aby vracala celé číslo v závislosti od výsledku porovnania argumentov elem1 a elem2 nasledovne:

  • ak *elem1 < *elem2 potom fcmp vráti celé číslo < 0
  • ak *elem1 == *elem2 potom fcmp vráti 0
  • ak *elem1 > *elem2 potom fcmp vráti celé číslo > 0

Pri porovnávaní elementov elem1 a elem2 symbol < znamená, že elem1 je menší ako elem2 v tom zmysle, že v utriedenom poli sa elem1 nachádza pred elem2. Podobne pre symbol >. 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 "Alexandra" je menší ako reťazec "Zora". Ak by sme však chceli triediť podľa dĺžky reťazca, potom reťazec "Alexandra" je väčší ako reťazec "Zora".

Triedenie poľa sa potom realizuje volaním funkcie qsort s patričnými parametrami.

Príklad

Použitie funkcie qsort ilustrujeme na nasledujúcom jednoduchom príklade:

#include <stdio.h>
#include <stdlib.h>
#define POCET_PRVKOV 6

int pole[POCET_PRVKOV] = { 45, 11, 100, 30, 20, 27 };

int Porovnaj_cele_cisla (const void * a, const void * b)
{
   // Parameter "a" je ukazovateľ typu "const void *". Preto ho pred použitím musíme pretypovať na poiter na "int". Čiže: "(int *)a". 
   // Pretože zápis "(int *)a" predstavuje ukazovateľ a my chceme porovnávať celé číslo, ktoré je uložené tam kde tento ukazovateľ ukazuje
   // musíme ďalej napísať: "*(int *)a". Týmto zápisom sa dostaneme k hodnote čísla na ktoré ukazuje predaný parameter "const void * a".
   // Podobne pre parameter "b".
   return ( *(int*)a - *(int*)b );  
}

int main ()
{
  int n;
  // Vzostupné utriedenie poľa:
  qsort (pole, POCET_PRVKOV, sizeof(int), Porovnaj_cele_cisla);

  // Výpis na monitor:
  for (n=0; n<POCET_PRVKOV; n++)
     printf ("%d ",values[n]);
  return 0;
}