Sunteți pe pagina 1din 65

PROGRAMAREA CALCULATOARELOR –

ALGORITMI

MODUL 1
CURS 3
3. TEHNICI DE CĂUTARE SI SORTARE
3.1. METODE DE CĂUTARE
 Obiectiv: Căutarea unor obiecte pe
baza valorii unui câmp (cheie) asociat
fiecărui obiect
- dacă obiectele nu sunt ordonate - căutare directă
- dacă obiectele sunt ordonate găsirea unui obiect se
poate face mai rapid

 Vom considera că obiectele sunt grupate în tablouri


unidimensionale şi că pentru cheie este definită o relaţie
de ordine

2
Căutarea binară
int CautareBinara(int *p, int n, int val) //iterativ
{
int inc, sfr, mij;
inc = 0;
sfr = n-1;
mij = (inc + sfr)/2;
while((inc <= sfr) && (val != p[mij]))
{
if(val < p[mij]) sfr = mij - 1;
else inc = mij + 1;
mij = (inc + sfr) / 2;
}
if(p[mij] == val)
return mij;
else
3
return -1;
}
int CautareBinara(int *p, int inc, int sfr, int val) //recursiv – divide et
// impera
{
int mij;
mij = (inc + sfr)/2;
if(p[mij] == val)
return mij;

if(inc <= sfr) {


if(p[mij] > val)
sfr = mij - 1;
else
inc = mij + 1;
return CautareBinara(p, inc, sfr, val);
}
return -1;
4
}
Funcţii de bibliotecă
 Biblioteca standard (search.h) pune la dispoziţie funcţii
pentru căutare

 In cazul unor vectori neordonaţi:

void *lfind(const void *key, const void *base,


size_t *num, size_t width,
int (*fcmp)(const void *, const void*));

void *lsearch(const void *key, void *base,


size_t *num, size_t width,
int (*fcmp)(const void *, const void *));
5
 În caz de succes funcţiile returnează adresa primului
element care are cheia căutată
 În caz de eşec:
 funcţia lfind( ) returnează pointerul null
 funcţia lsearch( ) adaugă elementul la sfârşitul tabloului
și returnează un pointer la elementul adăugat
 Funcţia de comparare fcmp( ) trebuie să returneze:
0, în caz de egalitate a elementelor
≠0, în caz contrar

• Ceilalți parametri sunt: key adresa cheii utilizate, base


adresa de început a tabloului, num adresa variabilei număr
de elemente, width dimensiunea unui element

 Versiunile mai noi pentru lfind() si lsearch() sunt _lfind() și


_lfind_s(), respectiv _lsearch() și _lsearch_s() (lfind() si 6
lsearch() nu mai sunt valabile)
#include<search.h>
#include<stdio.h>
#include<string.h>
#include<conio.h>
#define DIM 12
int cmp(char *arg1, char *arg2);
int addelem(char *key, char **tab, int nelem);
int main(void){
const char *luni[DIM] = {"ian", "feb", "mar", "apr", "mai", "iun" };
int i, nluni=6;
const char* key = "iul";
if (addelem(key, luni, nluni))
printf("Luna %s este deja in tablou.\n", key);
else {
nluni++;
printf("Luna \"%s\" a fost adaugata in tablou : ", key);
for (i = 0; i < nluni; i++)
printf("%s, ", luni[i]);
} 7
_getch(); }
int addelem(char *key, char **tab, int nelem)
{
int oldn = nelem;
_lsearch(&key, tab, (size_t *)&nelem, sizeof(char *),
(int(*)(const void *,const void *))cmp);
return(nelem == oldn);
}

int cmp(char *arg1, char *arg2)


{
return(strcmp(arg1, arg2));
} 8
 In cazul vectorilor ordonaţi (stdlib.h / search.h):

void *bsearch(const void *key, const void *base,


size_t nelem, size_t width,
int (*fcmp)(const void*, const void*));

 Parametrii au aceiași semnificație cu funcțiile precedente


doar că al 3-lea parametru e lungimea efectivă, size_t nelem
 Tabloul trebuie să fie ordonat crescător, iar funcţia de
comparare trebuie să returneze:
 o valoare negativă dacă *v1 < *v2
 zero dacă există egalitate între elemente
 o valoare pozitivă dacă *v1 > *v2

9
// utilizarea functiei de biblioteca bsearch()
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>

int compare_int(int *a, int *b);


int compare_float(float *a, float *b);

int main(void){
int int_values[] = {1, 2 , 3, 4, 5};
float float_values[] = {1.1, 2.2, 3.3, 4.4, 5.5};

int *int_ptr, int_value = 2, num;


float *float_ptr, float_value = 33.3;
10
num = sizeof(int_values)/sizeof(int);
//apel la functia de bibioteca bsearch() pentru sirul de numere intregi
int_ptr = (int *)bsearch(&int_value, int_values, num, sizeof(int),(int (*)
(const void *, const void *)) compare_int);

if (int_ptr)
printf("Valoarea %d a fost gasita!\n", int_value);
else
printf("Valoarea %d nu a fost gasita!\n", int_value);

num = sizeof(float_values)/sizeof(float);

11
//apel la functia de bibioteca bsearch() pentru sirul de numere reale
float_ptr = (float *)bsearch(&float_value, float_values, num,
sizeof(float),(int (*) (const void *, const void *)) compare_float);

if (float_ptr)
printf("Valoarea %3.1f a fost gasita!\n", float_value);
else
printf("Valoarea %3.1f nu a fost gasita!\n", float_value);
_getch();
}//end main()

12
int compare_int(int *a, int *b)
{
return(*a - *b);
} //end compare_int()

int compare_float(float *a, float *b)


{
if(*a < *b) return -1;
if(*a > *b) return 1;
return 0;
} //end compare_float()

13
Metode de sortare- Generalități
 Sortarea constă în rearanjarea obiectelor într-o ordine
specifică, prin permutarea acestora
 Pentru un set de obiecte S={a1, a2, ..., an}, prin sortare
rezultă setul S1={ak1, ak2, ..., akn}, astfel că, dându-se o
funcţie de ordonare f, este îndeplinită relaţia de ordine :
f(ak1) < f(ak2) <...< f(akn)
 Sortarea se face în raport cu o cheie asociată obiectelor
 Eficienţa unei metode de sortare se evaluează prin:
 numărul de comparaţii ale cheii
 numărul de permutări ale unui obiect

 Aceste operaţii sunt dependente de numărul de elemente


din set 14
CLASIFICAREA METODELOR DE SORTARE
Sortări prin interschimbare:
- Bubble Sort
- Cocktail Sort
- Comb Sort
- Quick Sort
Sortări prin selecție: - Selection Sort
- Heap Sort
Sortări prin inserție: - Insertion Sort
- Shell Sort
Sortări prin interclasare: - Merge Sort

Sortări fără comparații: - Radix sort


15
3.2.Metode de sortare
3.2.1. Metode simple de sortare

 Numărul de comparații este de ordinul n*n


 Sortarea se face "in situ" (pe loc)
 Dacă n este de ordinul sutelor sau chiar al miilor, timpii
de calcul sunt foarte apropiaţi pentru toate metodele de
sortare, astfel că, în acest caz, prevalează complexitatea
metodei de implementare.

16
 Sortarea prin interschimbare (bubble sort)

 se consideră perechi alăturate de elemente care se


prelucrează : (0,1), (1,2), (2,3),…
 dacă nu sunt în ordinea corectă, atunci elementele
perechii sunt schimbate între ele
 după prima parcurgere, cel mai mare element din vector
ajunge pe ultima poziţie

 se fac mai multe parcurgeri pentru a ordona întregul


tablou, iar la fiecare parcurgere tabloul prelucrat este mai
scurt, deoarece ultimele elemente sunt deja sortate

17
EXEMPLU BUBBLE-SORT

 Exemplu : 9 7 5 6 2
7 9 5 6 2 -> 7 5 9 6 2 -> 7 5 6 9 2 -> 7 5 6 2 9
5 7 6 2 9 -> 5 6 7 2 9 -> 5 6 2 7 9

5 6 2 7 9 -> 5 2 6 7 9

5 2 6 7 9 -> 2 5 6 7 9

 Observatie: după prima parcurgere a șirului pe ultima


poziție se găsește valoarea maximă din șir, la a doua
parcurgere pe penultima poziție se va găsi valoarea
maximă din subșirul rămas, etc.
18
void SortBubble(int *p, int n)
{
int i, j, temp;
for(i=0; i<n; i++) // parcurgeri
{
for(j=1; j<n-i; j++) // prelucrare sir curent
{
if(p[j-1] > p[j])
{
// interschimbare
temp = p[j-1];
p[j-1] = p[j];
p[j] = temp;
}
}
} 19
}
 Algoritmul poate fi îmbunătăţit dacă se observă că
după o parcurgere a tabloului în care nu s-a făcut nici
o interschimbare, sortarea este terminată

 Exemplu : 9 2 5 6 7:
 9 2 5 6 7 -> 2 9 5 6 7 -> 2 5 9 6 7 -> 2 5 6 9 7 -> 2 5 6 7 9
 25679

 Pentru aceasta se introduce o variabilă care să


semnalizeze interschimbarea

20
void SortBubble(int *p, int n)
{
int i, j, temp, flag;
for(i=0; i<n; i++) {
flag = 0;
for(j=1; j<n-i; j++) {
if(p[j-1] > p[j]) {
// interschimbare
temp = p[j];
p[j] = p[j-1];
p[j-1] = temp;
flag = 1;
}
}
// daca nu s-a facut nici o interschimbare
if(flag == 0) break;
} 21
}
//bubble sort (varianta do-while)
void SortBubbleD(int *p, int n)
{
int j, temp, flag;
do{
flag = 0;
for(j=0; j<n-1; j++) {
if(p[j] > p[j+1]) {
temp = p[j];
p[j] = p[j+1];
p[j+1] = temp;
flag = 1;
}
}//for
}while(flag != 0);
}
22
 Sortarea prin selecţie simplă
 se caută cel mai mic element şi se aduce pe prima
poziţie din şir prin interschimbare
 apoi se consideră tabloul format din elementele
2,3,...,N şi se caută cel mai mic element care se
aduce pe prima poziţie din şirul curent, ...

 Exemplu : 9 7 5 6 2
 9 7 5 6 2 -> 2 7 5 6 9 -> 2 5 7 6 9 -> 2 5 6 7 9

23
void SortSel(int *p, int n){
int i, j, pozmin, temp;
for(i=0; i<n; i++) // parcurgeri
{
// cautare pozitie cel mai mic element din sirul curent
pozmin = i;
for(j=i+1; j<n; j++) {
if(p[pozmin] > p[j])
pozmin = j;
}
// interschimbare cu elementul de pe prima pozitie
temp = p[pozmin];
p[pozmin] = p[i];
p[i] = temp;
} 24

}
 Sortarea prin inserţie simplă
 se consideră pe rând tablourile formate din primele
2,3,...,N elemente din vector
 se asigură că aceste tablouri sunt ordonate prin
aducerea noului element (2,3,...) pe poziţia
corespunzătoare valorii sale
 acest lucru implică deplasarea spre dreapta, cu o
poziţie, a elementelor cu chei mai mari decât cea a
noului element, astfel ca acesta să ajungă înaintea
acelor elemente, dar după elementele cu chei mai mici

25
EXEMPLU INSERȚIE SIMPLĂ

 Exemplu : 9 7 5 6 2

97 -> 79
7 9 5 -> 579
5 7 9 6 -> 5679
5 6 7 9 2 -> 25679

26
void SortIns(int *p, int n){
int i, j, temp;
for(i=1; i<n; i++) {
temp = p[i];
for(j=i-1; j>=0; j--) // tabloul curent
{
if(p[j] > temp)
p[j+1] = p[j]; // deplasare dreapta
else
break;
}
p[j+1] = temp;
} 27
}
 Observaţie:
 poziţia pe care trebuie adus noul element este
căutată secvenţial (pe un subşir deja ordonat),
astfel că algoritmul se poate îmbunătăţi
(elementele analizate fiind deja sortate), folosind
căutarea binară

28
void SortIns(int *p, int n){
int i, j, temp, inc, mij, sfr;
for(i=1; i<n; i++) {
temp = p[i];
// cautarea binara
inc = 0;
sfr = i-1;
mij = (inc + sfr)/2;
while(inc <= sfr) {
if(p[mij] > temp)
sfr = mij-1;
else
inc = mij+1;
mij = (inc + sfr)/2;
}
for(j=i-1; j>=inc; j--)
p[j+1] = p[j]; // deplasare dreapta
p[inc] = temp; 29

}
}
ALGORITMUL SHELL SORT
 ShellSort este un algoritm de sortare performant, bazat
pe sortarea prin inserție (InsertSort)

 Algoritmul lucrează pe tablouri de lungime N, fiind de


clasa O(N2)

 Cu toate acestea, algoritmul este vizibil mai rapid decât


algoritmii obișnuiți din clasa O(N2): InsertSort,
BubbleSort, SelSort, etc., fiind de circa 2 ori mai rapid
decât InsertSort, cel mai apropiat competitor din clasa
O(N2)

30
ALGORITMUL SHELL SORT
 Algoritmul ShellSort realizează deplasări pe distanţe
mari, sortând elementele aflate la distanţe mari prin
metoda inserţiei.

 După această sortare se continuă cu elemente aflate la


distanţe mai mici s.a.m.d. Se introduce noţiunea de n-
sortare: sortarea fiecărui al n-lea element.

 Diminuarea distanței se face folosind o secvenţă de


numere denumită şi secvenţă de intervale sau secvenţă
de spaţii.

 Uzual se utilizează secvenţa Knuth: h=3*h+1 (1, 4, 13,


40, 121, 364,…)
31
Exemplu Shell Sort

h=4

7 10 1 9 2 5 8 6 4 3
* *
2 10 1 9 7 5 8 6 4 3
* *
2 5 1 9 7 10 8 6 4 3
* *
2 5 1 6 7 10 8 9 4 3
* * *
2 5 1 6 4 10 8 9 7 3
* * *
2 3 1 6 4 5 8 9 7 10
32
h=1
2 3 1 6 4 5 8 9 7 10
*
1 2 3 6 4 5 8 9 7 10
*
1 2 3 4 6 5 8 9 7 10
*
1 2 3 4 5 6 8 9 7 10
*
1 2 3 4 5 6 7 8 9 10

33
void ShellSort(int *p, int max){
int stop=0,temp=0,h=0, i, j , k;
while( h<= max/3)
h = 3*h + 1; // se porneste de la un h>max/3
while(h>0) {
for(int i=h; i<max; i++) { // se ia fiecare element de la pozitia h
// pana la sfarsit
temp=p[i];
j=i;
while((j>=h)&&(p[j-h]>temp)) {
p[j]=p[j-h]; // deplasare dreapta
j=j-h;
}
p[j]=temp;
} //for
h = (h-1)/3; // modificarea distantei de comparare
}// while 34
}
 Observaţii:
 toate exemplele anterioare realizează sortarea prin
ordonarea crescătoare a unor numere întregi
 Temă:
 modificaţi aceste funcţii de sortare pentru a realiza
sortări prin ordonare descrescătoare pentru toate
tipurile aritmetice

35
 Exemplul 1: utilizarea unei funcţii de sortare:
#include <iostream>
using namespace std;

void SortIns(int *p, int n);

int main( ){
int i, n, *tab;
cout <<"Cate numere: ";
cin >> n;

tab = new int[n];


if(tab != 0) {
cout << "Introduceti " << n << " numere intregi:" << endl;
for(i=0; i<n; i++){
cout << "\tNumarul "<<(i+1)<<": ";
cin >> *tab++; 36
}
tab -= n; //revin la inceputul tabloului
SortIns(tab, n);

cout << "\nNumerele sortate sunt: "<<endl;


for(i=0;i<n;i++)
cout << *tab++ <<" ";
cout << endl;

tab -= n; //revin la inceputul tabloului


delete [ ] tab;
}
}

void SortIns(int *p, int n)


{
// corp functie de sortare
} 37
Exemplul 2
#include <iostream>
using namespace std;
void BubbleSort(const char **names, const int size);
int main(void){
int dimc = 6;
const char *tabc[] = { "abc", "xyz", "acd", "axyz", "bc", "eltcti" };
BubbleSort(tabc, dimc); //sortare crescatoare dupa cod
cout << "\nSirurile sortate: ";
for (int i = 0; i<dimc; i++)
cout << tabc[i] << ", ";
cout << endl;
cin.get();
} 38
void BubbleSort(const char **names, const int size) {
int swapped;
do {
swapped = 0;
for (int i = 0; i < size - 1; ++i) {
if (strcmp(names[i], names[i + 1]) > 0) {
const char *temp = names[i];
names[i] = names[i + 1];
names[i + 1] = temp;
swapped = 1;
} // if
} // for
} while (swapped);
}

39
Exemplul 3
#include <iostream>
using namespace std;
int fcmp(char *s1, char *s2);
void BubbleSort (char **names, const int size);
int main(void) {
int dimc = 6;
const char *tabc[] = {"abc", "xyz", "acd", "axyz", "bc", "eltcti"};
BubbleSort(tabc, dimc); //sortare crescatoare dupa dimensiune
cout << "\nSirurile sortate: ";
for(int i=0;i<dimc; i++)
cout << tabc[i] << ", ";
cout << endl;
}
40
void BubbleSort (char **names, const int size) {
int swapped;
do {
swapped = 0;
for (int i = 0; i < size-1; ++i) {
if (fcmp(names[i], names[i+1]) > 0 ) {
char *temp = names[i];
names[i] = names[i+1];
names[i+1] = temp;
swapped = 1;
}
}
} while (swapped);
}

int fcmp(char *s1, char *s2){


return(strlen(s1)-strlen(s2));
// return strcmp(s1, s2);
41
}
 Temă:
 modificaţi aceste funcţii de sortare pentru a include
funcţia de comparaţie la apelul funcţiei de sortare

void Sort(char **tab, int n, int(*fcmp)(char *s1, char *s2));

42
43
3.2.2. Metode avansate de sortare

 Sunt algoritmi ce permit reducerea numărului de


comparaţii până la nlog(n)
 Prezintă o complexitate mai mare, exprimată prin
recursivitate, structuri de date specializate sau utilizarea
mai multor tablouri pentru sortare
 Eficienţa acestor algoritmi este evidentă pentru
dimensiuni mari, începând cu ordinul miilor (lucru ce
reiese şi din raportul n/log(n))

44
SORTAREA PRIN INTERCLASARE (MERGE SORT)
 Principiul metodei: se bazează pe obținerea din 2 vectori
ordonati a unui vector ordonat ce conține elementele
celor 2 vectori.
 Sortarea prin interclasare utilizează metoda Divide et
Impera
 Se împarte vectorul inițial nesortat în secvențe din ce în
ce mai mici, astfel încât fiecare secvență să fie ordonată
la un moment dat și apoi interclasată cu o altă secvență
din vector.
 Practic interclasarea va începe când se ajunge la o
secvență formată din două elemente. Aceasta odată
ordonată se va interclasa cu o alta corespunzătoare, iar
apoi procesul va continua la următorul nivel ce implică
perechi de câte 4 elemente, etc.
45
46
#include<iostream>
using namespace std;
void interclas(int *a,int i,int m,int j);
// i- pozitia de inceput a primului subsir, m- pozitia de sfarsit a primului
subsir,
// j- pozitia de sfarsit al celui de-al doilea subsir
void divimp(int *a,int i,int j);
// i- indicele primului element din vector,
// j - indicele ultimului element din vector
#define DIM 1000
void main(){
int a[DIM],n;
cout<<"n="; cin>>n;
for(int i=0;i<n;i++){
cout<<"a["<<i<<"]=";
cin>>a[i];
} 47
divimp(a,0,n-1);
for(int i=0;i<n;i++)
cout<<a[i]<<' ';
} //main

void divimp(int *a,int i,int j)


{
if (i<j)
{
int m=(i+j)/2;
divimp(a,i,m); // apel functie pentru prima jumatate a sirului
divimp(a,m+1,j); // apel functie pentru a doua jumatate a sirului
interclas(a,i,m,j); // interclasarea celor 2 subsiruri
}
}
48
void interclas(int *a,int i,int m,int j) {
int b[DIM];
int x=i; // pentru deplasarea in primul subsir
int k=0;
int y=m+1; // pentru deplasarea in al doilea subsir
while(x<=m && y<=j)
if (a[x]<a[y])
b[k++]=a[x++];
else
b[k++]=a[y++];
while (x<=m)
b[k++]=a[x++]; // restul elementelor din primul subsir
while (y<=j)
b[k++]=a[y++]; // restul elementelor din al doilea subsir
int t=i;
for (k=0;k<(j-i)+1;k++)
a[t++]=b[k]; // mut elementele sortate in sirul initial 49
}
Observații:
 numărul de operații elementare executate este de ordinul
O(nlog(n)).
 pentru tablouri cu număr mare de componente, timpul de
calcul este mult mai mic în cazul sortării prin interclasare,
decât în cazul folosirii algoritmilor simpli, cum ar fi cel al
selecţiei, inserţiei sau al bulelor, a căror complexitate
este O(n2).
 Algoritmul de sortare prin interclasare consumă însă de
două ori mai multă memorie decât cei simpli menționaţi,
deoarece necesită spaţiu suplimentar pentru tabloul
auxiliar .

50
 Algoritmul QuickSort
 Se bazează pe noţiunea de partiţie
 Prin partiţionarea datelor se înţelege împărţirea
acestora în două grupuri, astfel încât toate elementele
cu chei mai mari decât o valoare dată se află într-un
grup, iar cele cu valori mai mici se află în celălalt grup

 Etapele partiţionării :
 se consideră un element x al tabloului numit şi element
pivot
 se parcurge tabloul de la stânga până ce se găseşte un
element ai mai mare ca x
 se parcurge tabloul de la dreapta până ce se găseşte un
element aj mai mic ca x

51
 se interschimbă ai cu aj
 se actualizează i şi j prin incrementare, respectiv
decrementare
 se repetă paşii anteriori până când cele două scanări se
întâlnesc
 în acest moment tabloul este partiţionat, adică :
 în stânga lui x se găsesc numai elemente mai mici ca x
 în dreapta lui x se găsesc numai elemente mai mari ca x
 a[k] <= x, k = 0,...,i-1
 a[k] >= x, k = j+1,...,n
 a[k] = x, k = j+1,...,i-1

52
 După prima partiţionare, şirul nu este încă ordonat
 De aceea se continuă, la stânga şi la dreapta pivotului,
în acelaşi mod.
- algoritmul QuickSort are o natură recursivă

QuickSort is
{
If (right-left) == 0 then
Return
Else
pivot = Tablou[right]; // sau Tablou[middle]
partition = Partitionare(left, right, pivot)
QuickSort(left, partition-1);
QuickSort(partition+1, right);
EndIf 53
}
 Pivotul este elementul din mijlocul sirului

88 6 57 71 60 42 83 73 48 65

48 6 57 71 60 42 83 73 88 65

48 6 57 42 60 71 83 73 88 65

6 48 57 42 60 71 65 73 88 83

6 48 42 57 60 65 71 73 83 88

6 42 48 57 60 65 71 73 83 88
Pivotul este ultimul element din șir
88 6 57 71 60 42 83 73 48 65
inc sfr

65 6 57 71 60 42 83 73 48 88
inc

65 6 57 48 60 42 83 73 71 88
inc sfr

42 6 57 48 60 65 83 73 71 88
sfr inc inc

42 6 57 48 60 65 71 73 83 88
sfr inc

6 42 57 48 60 65 71 73 83 88

6 42 57 48 60 65 71 73 83 88

6 42 48 57 60 65 71 73 83 88
void QuickSort(int *p, int prim, int ultim)
{
int inc, sfr, pivot, temp, mij;
inc = prim;
sfr = ultim;
mij=(prim+ultim)/2;
pivot = p[mij];
// partitionare
do {
while(p[inc] < pivot)
inc++;
while(p[sfr] > pivot)
sfr--;
56
if(inc < sfr) {
temp = p[inc];
p[inc] = p[sfr];
p[sfr] = temp;
}
if(inc <= sfr) {
sfr--;
inc++;
}
}while(inc <= sfr);
// apel recursiv
if(prim < sfr)
QuickSort(p, prim, sfr);
if(inc < ultim)
QuickSort(p, inc, ultim);
57
}
 Alegerea valorii pivot :
 pivotul trebuie să reprezinte valoarea cheii unui element
din tablou
 se poate alege la întâmplare, dar trebuie evitate
valoarea minimă, respectiv maximă

 Valori uzuale :
 elementul din mijlocul tabloului
 ultimul element din tabloul partiţionat
 valoarea mediană între primul, ultimul şi elementul din
mijlocul tabloului

58
 Biblioteca standard (stdlib.h) pune la dispoziţie funcţia:
void qsort(void *base, size_t nelem, size_t width,
int(*fcmp)(const void *, const void *));

 Funcţia de comparare, definită de utilizator pentru


sortarea crescătoare trebuie să returneze :
 < 0 dacă *v1 < *v2
 0 dacă *v1 == *v2
 > 0 dacă *v1 > *v2

 Pentru ordonare descrescătoare, valorile negativă și


pozitivă returnată se vor inversa. Tabloul unidimensional
de ordonat poate să conţină şi alte tipuri de date (şiruri de
caractere sau structuri).
59
// Exemplu tablou de intregi ordonat cu qsort()
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
int compara(const void* val1, const void* val2);
int (*fcmp)(const void*, const void*);
#define DIM 20

void main(void){
int i,n,tab[DIM];
printf("Introdu dimensiune tablou: ");
scanf("%d",&n);
printf("Introdu elemente tablou:\n");
for(i=0;i<n;i++){
printf("tab[%d] = ",i);
scanf("%d",&tab[i]);
}
fcmp=compara; //fcmp va avea adresa functiei de comparare 60
qsort(tab,n,sizeof(i),fcmp);
puts("Tabloul ordonat este");
for(i=0;i<n;i++)
printf("%d ",tab[i]);
_getch();
}//main
int compara(const void * val1, const void* val2)
{
//return((*(int*)val1) - (*(int*)val2)); //ordonare crescatoare
return((*(int*)val2) - (*(int*)val1)); //ordonare descrescatoare
} //compara

61
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>

struct datac {
int an;
int luna;
int zi;
};
struct pers {
char numep[12];
struct datac datan;
};
62
int cmp( const struct pers *a, const struct pers *b);
void main(void){
struct pers angaj[ ] = {
{"x1", {1980, 6,6}},
{"x2", {1960, 5, 5}},
{"x3", {1960, 1,5}},
{"x4", {1961, 12, 32}},
{"x5", {1980, 2, 29}}
};
int i;
int nang = sizeof(angaj)/sizeof(struct pers);
// apel functie de sortare
qsort((void *)angaj, nang, sizeof(angaj[0]), (int (*)(const void*, const
void*))cmp);
printf("Datele sortate :\n");
for (i = 0; i < nang; i++) {
printf("\t%s, %d, %d, %d\n", angaj[i].numep, angaj[i].datan.an,
angaj[i].datan.luna, angaj[i].datan.zi);
}
_getch(); 63
}
int cmp(const struct pers *a, const struct pers *b){
if((a->datan).an > (b->datan).an) return 1;
else
if((a->datan).an < (b->datan.an)) return -1;
else {
if((a->datan).luna > (b->datan).luna) return 1;
else if((a->datan).luna < (b->datan).luna) return -1;
else {
if((a->datan).zi > (b->datan).zi)
return 1;
else if((a->datan).zi < (b->datan).zi)
return -1;
else
if((strcmp(a->numep, b->numep)>0)) return 1;
else if((strcmp(a->numep, b->numep)<0))
return -1;
return 0;
} //else 64
}// else
}
65

S-ar putea să vă placă și