Vous êtes sur la page 1sur 56

1

LSI 1

Les algorithmes de tri


Les algorithmes de recherche
2

LSI 1

Problème de tri
Tri par sélection
Présentation informelle
Exemple d’animation
Algorithme
Réalisation en C
Complexité
Tri par insertion
Présentation informelle
Exemple d’animation
Algorithme
Réalisation en C
Complexité
Tri par sélection vs tri par insertion
Tri : utilisation
3

LSI 1

Le problème de tri
Vue fonctionnelle
Tableau à trier Tableau trié
Grandeur d’entrée Problème de tri Grandeur de sortie

• Pour pouvoir spécifier d’une façon assez précise le problème de tri


on doit dégager une relation entre les grandeurs d’entrée et les
grandeurs de sortie
▫ Pour le problème de tri une telle relation est traduite par les deux contraintes
ou propriétés
 Le tableau trié constitue une permutation du tableau à trier
 Le tableau trié est dans le bon ordre
 soit l’ordre croissant soit l’ordre décroissant au sens large (présence de doublons)
4

LSI 1

Le problème de tri
• Exigence
▫ Les éléments à trier sont stockés dans un tableau
▫ Les algorithmes de tri exigent que le tri se fasse in-situ, c'est-à-dire il faut que le résultat
soit mémorisé au même endroit que les données initiales

pour des raisons d’économie (utilisation du même tableau)

• Il existe plusieurs algorithmes permettant de réaliser l’opération de tri. Ces


algorithmes sont classés en deux catégories
▫ Algorithmes élémentaires : tri par sélection, tri par insertion, etc.
▫ Algorithmes évolués : tri par tas, tri rapide, etc.
5

LSI 1

Le problème de tri
• Démarche à suivre pour présenter les algorithmes

▫ Présentation informelle ou principe

▫ Algorithme en Pseudo-code

▫ Réalisation en C

▫ Complexité ou coût (temporelle et spatiale)


6

LSI 1

Tri par sélection : Présentation informelle (Principe ou idée)

▫ L’algorithme de tri par sélection (selection sort) consiste


 à trouver l’emplacement (indice) de l’élément le plus petit du tableau (la suite initiale
<a1, a2 , …, an>) c'est-à-dire un entier « m » telle que ai >=am pour tout i appartenant à
[1,n]
 avec n est la taille du tableau à trier
 une fois m est trouvé on échange a1 et am

 on recommence ces deux opérations sur la nouvelle suite < a2 , a3 , …, an>


 Chercher l’emplacement de l’élément le plus petit et échanger a2 et am

 ainsi de suite jusqu’à ce que la suite soit formée d’un seul élément <an>
 avec an le maximum de la suite initiale
7

LSI 1

Tri par sélection : Exemple d’animation


2, 56, 4, -7, 0, 78, -45, 10 -45, -7, 0, 2, 4, 78, 56, 10
-45, -7, 0, 2, 4, 78, 56, 10
2, 56, 4, -7, 0, 78, -45, 10
-45, 56, 4, -7, 0, 78, 2, 10 -45, -7, 0, 2, 4, 78, 56, 10
-45, -7, 0, 2, 4, 10, 56, 78
-45, 56, 4, -7, 0, 78, 2, 10
-45, -7, 4, 56, 0, 78, 2, 10
-45, -7, 0, 2, 4, 10, 56, 78
-45, -7, 4, 56, 0, 78, 2, 10 -45, -7, 0, 2, 4, 10, 56, 78
-45, -7, 0, 56, 4, 78, 2, 10
-45, -7, 0, 2, 4, 10, 56, 78
-45, -7, 0, 56, 4, 78, 2, 10
-45, -7, 0, 2, 4, 78, 56, 10
8

LSI 1

Tri par sélection : Pseudo Code


Procédure Tri_Sélection(Entrée n : entier, E/S A: Tab) Entrée : A[1..n] est un tableau d’entiers, n≥
Var 1. Sortie / Résultat : les éléments de A sont
i,j,minidx : entier ordonnés par ordre croissant
tmp : entier
Début
pour i de 1 à n − 1 faire • Les données sont rangées dans un
minidx ← i tableau A entre les indices 1 et n
pour j de i + 1 à n faire
si (A[j] < A[minidx]) alors • On utilise trois variables entières
minidx ← j (positives) notées i, j et minidx et
finsi
finfaire // boucle portant sur j
une variable temporaire tmp de
même type que les éléments du
// maintenant A[minidx] = min{A[i], . . . , A[n]} tableau pour l’échange entre A[i]
si i <> minidx alors
//echanger A[i] et A[minidx]
et A[minidx]
tmp ← A[i]; • Pour chaque itération de la boucle
A[i] ← A[minidx]
A[minidx] ← tmp portant sur i, on cherche le plus
finsi petit élément de la liste qui se
finfaire // boucle portant sur i trouve entre les indices i et n
Fin Tri_Sélection
9

LSI 1

Tri par sélection : Réalisation en C

• Pour réaliser un algorithme en C, on fait appel au concept de sous-


programme
▫ Procédure
▫ Fonction

• l’algorithme de tri est défini sous forme de procédure


▫ Il reste à définir la manière de communiquer entre le sous-programme (ici
une procédure) et son environnement (appelant)
▫ On distingue les schémas suivants
10

LSI 1

Tri par sélection : Réalisation en C

Schéma 1 : Communication implicite Schéma 2 : Communication explicite

#define n 100 /* le tableau à trier est passé comme


/* variable globale */ paramètre à la fonction */
int a[n]; void tri_selection ( int a[], unsigned n)
void tri_selection ( ) {
{ ….
…. }
} /* a et n sont des paramètres formels */
/* a est partagée par le sous-programme et
son environnement */
11

LSI 1

Tri par sélection : Réalisation en C


Réalisation en C : Schéma 1
#define n 100 /* partie exécutive */
int a[n] ; /* tableau à trier*/ for (i=0 ; i<n-1 ; i++)
void tri_selection() { /* recherche de m */
{ m=i;
/* Partie déclarative : variables locales*/
for(j=i+1 ; j<n ; j ++)
unsigned i ;
if(a[j] < a[m])
/* varie entre 0 et n-2. Elle indique l’avancement dans le tri */
m=j;
unsigned j ; /* échange entre a[i] et a[m] */
/* varie entre i+1 et n-1. Elle permet de calculer m */ t=a[i] ;
a[i]=a[m] ;
unsigned m ; a[m]=t ;
/*correspond à l‘emplacement de l’élément le plus petit entre i } /* fin for i */
et n-1 */ }/* fin tri_selection */

int t;
/*utilisée pour l’échange entre a[i] et a[m]*/
12

LSI 1

Tri par sélection : Réalisation en C


Tester la procédure de tri
• résultat prévu à l’avance • Jeu de données
• résultat observés suite à l’exécution du programme sur un jeu
de données bien déterminées ▫ Données de test={18,14,10,8,4}
• comparaison • Résultat prévu : 4 8 10 14 18
#include <stdio.h>
#define n 5
• Résultat observé
int a[n] ={18,14,10,8,4}; ▫ exécution du programme …….
void main()
{
tri_selection ();
for(i=0 ;i<n ; i++)
{
printf(“%d”, a[i]”);
}
}
13

LSI 1

Tri par sélection : Complexité

• La complexité est une notion permettant de calculer le coût d’un


algorithme séquentiel
▫ Un algorithme consomme deux types de ressources
 Ressource mémoire : on parle de la complexité en espace d’un algorithme
 Ressource temps : on parle de la complexité en temps d’un algorithme

• La complexité permet de comparer objectivement des algorithmes


censés résoudre le même problème
▫ Elle se fait indépendamment d’un ordinateur donné
▫ C’est une fonction mathématique qui possède comme argument la taille du
problème caractérisée par un ou plusieurs paramètres
14

LSI 1

Tri par sélection : Complexité

• Consommation de la ressource temps : efficacité


▫ Une notion théorique : complexité
 Elle ne dépend pas d’un ordinateur particulier
▫ Temps de réponse
 Dépend de l’ordinateur sur lequel l’algorithme est exécuté

• Le problème de tri est caractérisé par un seul paramètre appelé n


▫ Qui correspond au nombre d’éléments du tableau à trier
15

LSI 1

Tri par sélection : Complexité


• Complexité spatiale
▫ La complexité spatiale est de l’ordre de n ; en effet le tri s’effectue dans le même tableau
• Complexité temporelle
Pour une itération donnée (correspondant à la boucle for externe)
•il s’agit de calculer le nombre de fois où la comparaison (a[j]<a[m]) est
exécutée (ça correspond également au nombre de fois où la boucle for
interne est exécutée) :
Pour i=1 on fait (n-1) comparaisons
Pour i=2 on fait (n-2) comparaisons

Pour i donné on fait (n-i) comparaisons

Pour i =n-1 on fait 1 comparaison
•il s’agit de calculer également le nombre d’échanges
Pour chaque itération on fait 1 échange
On suppose que les instructions permettant d’assurer l’échange forment
• La complexité totale correspond donc à une « macro instruction » (3 instructions pour l’échange)
▫ (n-1) + (n-2) + …+1 = n(n-1)/2 comparaisons
▫ (n-1) échanges
• Elle est donc de l’ordre de n2 quand n est très grand : O(n2)
16

LSI 1

Tri par sélection : Complexité

• La complexité temporelle du tri par sélection est aussi bien dans le


pire des cas que dans le meilleur des cas (et donc qu’en moyenne)
en O(n2)

• Ce n’est donc pas un tri très efficace, mais en revanche c’est un


tri très simple
•Le tri par sélection ne prend pas en considération l’ordre de la
configuration initiale du tableau à trier
•Il est insensible à la configuration initiale
17

LSI 1

Tri par insertion : Présentation informelle (Principe ou idée)

Tri du joueur de cartes

• l’algorithme de tri par insertion (insertion sort) consiste à


procéder par étape
 à la ième étape (i variant de 2 à n), on suppose que les (i-1) premiers
éléments sont déjà triés
 on considère alors le ième élément (qu’on appelle aussi clé), il s’agit donc de
l’insérer à sa bonne position dans la sous suite de (i-1) éléments
18

LSI 1

Tri par insertion : Présentation informelle


(Principe ou idée)

 on le compare successivement aux éléments précédents, en commençant


par le (i-1)ème jusqu’à trouver la bonne place de clé (c’est-à-dire entre
deux éléments successifs, l’un étant plus petit et l’autre plus grande que
clé), ou bien en tout premier si clé est plus petite que les i premiers
éléments
 au fur et à mesure, on décale « d’une case vers la droite » les éléments plus grands que clé de façon à
anticiper la place de ces éléments après insertion de clé
 on met donc clé à la bonne place
 à l’issue de cette étape, les i premiers éléments sont donc triés

 On commence avec i=2


19

LSI 1

Tri par insertion : Exemple d’animation

2, 56, 4, -7, 0, 78, -45, 10


2, 56, 4, -7, 0, 78, -45, 10
2, 56, 4, -7, 0, 78, -45, 10
2, 4, 56, -7, 0, 78, -45, 10
-7, 2, 4, 56, 0, 78, -45, 10
-7, 0, 2, 4, 56, 78, -45, 10

-45, -7, 0, 2, 4, 56, 78, 10

-45, -7, 0, 2, 4, 10, 56, 78


20

LSI 1

Tri par insertion : Pseudo Code


Entrée : A[1..n] est un tableau d’entiers, n≥
PROCEDURE Tri_Insertion(Entrée n : entier, E/S A:
Tab) 1. Sortie / Résultat : les éléments de A sont
ordonnés par ordre croissant
VAR
i,j : entier
v : entier • Les données sont rangées dans un
DEBUT tableau A entre les indices 1 et n
pour i de 2 à n faire
• On utilise deux variables entières
v=A[i]
j←i
(positives) notées i et j et une
tant que ((j > 1) et (A[j-1] > v)) faire variable v de même type que les
A[j] ← A[j-1] éléments du tableau pour
j ← j-1 l’élément à insérer
finfaire // boucle tant que • Pour chaque itération de la boucle
A[j] ← v portant sur i, on cherche la
finfaire // boucle pour position d’insertion entre les
FIN Tri_Insertion indices i et 1
21

LSI 1

Tri par insertion : Réalisation en C


Réalisation en C
/* partie exécutive */
# define n 100 for (i=1 ;i<n ;i++)
/* variables globales */ {
/*insertion de a[i]*/
int a[n] ;/*a : tableau à trier*/ v=a[i];
void tri_insertion() j=i;
/* faire les décalages éventuels. Le nombre de décalages n’est pas connu a
{ priori, on opte donc pour le schéma while plutôt que le schéma for */
/* variables locales */ while ((j>0) && (a[j-1]>v))
{
unsigned i ; a[j]=a[j-1];
j--;
/* niveau d’avancement dans le tri */
/*passer à l’élément précédent*/
unsigned j ; } /* fin while */
/* à la sortie de la boucle j<=0 || a[j-1] <= v */
/* pour le décalage */ a[j]=v ;
int v ; } /* fin for */
} /* fin tri_insertion */
/*élément à insérer*/
22

LSI 1

Tri par insertion : Complexité

• Complexité spatiale
▫ est de l’ordre de n notée O(n)
 en effet le tri se fait dans le même tableau

• Complexité temporelle
▫ on identifie l’opération atomique (ou élémentaire) à comptabiliser
 on s’intéresse à la boucle interne (while) et plus précisément, on s’intéresse à
l’expression qui gouverne while à savoir ((j>0) && (a[j-1]>v))
 on va comptabiliser le nombre de comparaisons a[j-1]>v pour une itération donnée (de la
boucle externe)
 le nombre de comparaisons (a[j-1]>v) n’est pas connu a priori, il dépend de la configuration
initiale du tableau a, on distingue les cas suivants
23

LSI 1

Tri par insertion : Complexité


• Meilleur des cas (cas favorable ou optimiste)
▫ Ce cas peut être traduit par un tableau trié dans le bon ordre
▫ La comparaison est effectuée (n-1) fois
 En effet, à chaque itération (de la boucle externe) la comparaison est exécutée une seule fois
• Elle est de l’ordre de n c'est-à-dire en O(n)

• Pire des cas (cas défavorable ou pessimiste)


▫ Ce cas est traduit par un tableau trié dans l’ordre inverse
▫ Le nombre de comparaisons est égal à
 1+ 2+ 3+…+ (n-1)=n(n-1)/2
• Elle est de l’ordre de n2 c'est-à-dire en O(n2)

• Cas moyen
▫ La complexité du cas moyen est encadrée entre le cas minimum (O(n)) et le cas maximum (O(n2))
▫ Une approximation est O(n2/2)
24

LSI 1

Tri par insertion : Complexité


Meilleur des cas Pire des cas
• Tout Tableau trié • Tout tableau trié dans l’ordre inverse
i=2 i=2
56, 10, 4, 2, 0, -7, -45 1 comparaison
-45, -7, 0, 2, 4, 10, 56 1 comparaison
i=3 1 décalage
i=3
10, 56, 4, 2, 0, -7, -45 2 comparaisons
-45, -7, 0, 2, 4, 10, 56 1 comparaison i=4 2 décalages
i=4 4, 10, 56, 2, 0, -7, -45 3 comparaisons
-45, -7, 0, 2, 4, 10, 56 1 comparaison i=5 3 décalages
i=5 2, 4, 10, 56, 0, -7, -45 4 comparaisons
-45, -7, 0, 2, 4, 10, 56 1 comparaison i=6 4 décalages
0, 2, 4, 10, 56, -7, -45 5 comparaisons
i=6
i=7 5 décalages
-45, -7, 0, 2, 4, 10, 56 1 comparaison -7, 0, 2, 4, 10, 56, -45 6 comparaisons
i=7
-45, -7, 0, 2, 4, 10, 56 1 comparaison -45, -7, 0, 2, 4, 10, 56
25

LSI 1

Tri par insertion : Complexité


Meilleur des cas Pire des cas
• Pour n=7 • Pour n=7
▫ nous avons (n-1) comparaisons ▫ nous avons
▫ nous avons 0 décalage  1+ 2+ …+ (n-1) comparaisons
▫ nous avons
 1+ 2+ …+ (n-1) décalages
26

LSI 1

Tri par sélection vs tri par insertion


• Complexité spatiale
▫ Elle est en o(n) pour les deux algorithmes
▫ Elle est linéaire par rapport à n
▫ Les variables qui ne sont pas liées directement au problème à résoudre peuvent être négligées
 Elles sont considérées comme des variables simples

• Complexité temporelle
▫ L’algorithme de tri par sélection ne prend pas en compte la configuration initiale du tableau à trier
 Ceci explique Cmin= Cmoy= Cmax Elle est O(n2)
▫ Généralement on compare les algorithmes résolvant le même problème sur la base de la complexité au pire des
cas
 Dans le cas pessimiste les deux algorithmes (tri par sélection et tri par insertion) présentent la même complexité O(n2)
27

LSI 1

Tri par sélection vs tri par insertion


• Le tri par insertion a une complexité en moyenne (en onsidérant
l’exécution sur des configurations différentes) de même ordre que
celle du tri par sélection
▫ néanmoins, si les données à trier sont souvent presque triées (dans le sens
souhaité), il est préférable de choisir le tri par insertion
 il est plus efficace

▫ en effet, le tri par insertion a un comportement plus naturel puisqu’il est


sensible à la disposition initiale des éléments
 il est donc sensible à la configuration initiale du tableau
28

LSI 1

Tri par sélection vs tri par insertion


• Les deux algorithmes de tri sont stables
▫ Ils ne changent pas l’ordre d’apparition des éléments identiques

Un tri est stable s’il préserve l’ordre d’apparition des objets en cas d’égalité des clés.
Cette propriété est utile par exemple lorsqu’on trie successivement sur plusieurs clés
différentes
• Si l’on veut ordonner les étudiants par rapport à leurs noms puis à leurs
moyennes générales, on veut que les étudiants qui ont la même moyenne
apparaissent dans l’ordre lexicographique de leurs noms
29

LSI 1

Tri : Utilisation
Tri par insertion Tri par sélection
void main() void main()
{ {
int a[5]={20,30,40,50,60}; int a[5]={20,30,40,50,60};
int b[5]={60,50,40,30,20}; int b[5]={60,50,40,30,20};
int c[8]={3,8,5,4,12,13,100,12}; int c[8]={3,8,5,4,12,13,100,12};
unsigned i; unsigned i;
tri_insertion(a,5); tri_selection(a,5);
for(i=0;i<5;i++) for(i=0;i<5;i++)
printf("%d\t"; a[i]); printf("%d\t"; a[i]);
printf("\n"); printf("\n");
tri_insertion(b,5); tri_selection(b,5);
for(i=0;i<5;i++) for(i=0;i<5;i++)
printf("%d\t"; b[i]); printf("%d\t"; b[i]);
printf("\n"); printf("\n");
tri_insertion(c,8); Activation Appel tri_selection(c,8);
for(i=0;i<8;i++) ou Invocation for(i=0;i<8;i++)
printf("%d\t"; c[i]); printf("%d\t"; c[i]);
} }
30

LSI 1

Recherche séquentielle
Présentation informelle
Algorithme
Réalisation en C
Complexité
Recherche séquentielle avec sentinelle
Présentation informelle
Réalisation en C
Complexité
Comparaison avec et sans sentinelle
Recherche dichotomique
Présentation informelle
Algorithme
Réalisation en C
Complexité
31

LSI 1

Problème de recherche

Vue fonctionnelle
•Tableau Problème de
Résultat
•x recherche

• Un problème de recherche est un problème ayant deux issues


▫ Négative ou échec : l’élément recherché ne se trouve pas dans le tableau
▫ Positive ou succès : l’élément recherché se trouve dans le tableau
32

LSI 1

Recherche séquentielle : Présentation informelle

▫ L’algorithme de recherche séquentielle (ARS) consiste

 à comparer successivement (linéairement ou séquentiellement) tous les


éléments (de gauche à droite ou de droite à gauche) du tableau avec
l’élément recherché jusqu’à le rencontrer ou bien atteindre la fin du
tableau

 cet algorithme fonctionne sur un tableau trié ou non


33

LSI 1

Recherche séquentielle : Pseudo Code


Solution 1
FONCTION Recherche_Séquentielle (x : entier, A : Tab, n : entier) : booleen
VAR
Entrée : A[1..n] est un tableau d’entiers, n≥ 1
i : entier x un entier
Sortie / Résultat : vrai si l’élément recherché coïncide
DEBUT avec un élément du tableau, faux sinon
pour i de 1 à n faire
si (A [i] = x) alors
• Il y a n données
retourner vrai // issue positive
• Les données se trouvent dans un
finsi tableau A à partir de l’indice 1
finpour • La donnée à rechercher est notée x
retourner faux // issue négative
• On utilise un entier i
FIN Recherche_Séquentielle
34

LSI 1

Recherche séquentielle : Pseudo Code


Solution 2
FONCTION Recherche_Séquentielle (x : entier, A: Tab, Entrée : A[1..n] est un tableau d’entiers, n≥ 1
n : entier) : booleen x un entier
Sortie / Résultat : vrai si l’élément recherché coïncide
VAR avec un élément du tableau, faux sinon
i : entier
DEBUT
i←1 • Il y a n données
tant que ((i<=n) et (A[i]<>x)) faire • Les données se trouvent dans un
i ← i+1 tableau A à partir de l’indice 1
finfaire
• La donnée à rechercher est notée x
si (i<=n) alors
retourner vrai // issue positive • On utilise un entier i
sinon
retourner faux // issue négative
finsi
FIN Recherche_Séquentielle
35

LSI 1

Recherche séquentielle : Réalisation en C


Données du problème
• Soit un annuaire téléphonique comportant
un ensemble de paires <nom, tel>
▫ nom est le nom de l’abonné
▫ tel son numéro

• On voudrait chercher le numéro de


téléphone d’un abonné donné

• On choisit de représenter l’annuaire par


une table ( deux tableaux indicés en
parallèle ou tableau de structure)
36

LSI 1

La notion de table : définition


• Une table est un ensemble de n-uplets <x1, X2, …, xn>
▫ Chaque élément de la table est un n-uplet
 Un ensemble de points dans le plan forme une table
 Chaque élément est une paire <x,y>
 Un ensemble de points dans l’espace est une table
 Chaque élément est un triplet <x, y, z>
 Un annuaire téléphonique constitue une table
 Chaque élément est une paire <nom, tel>
37

LSI 1

La notion de table : représentation physique


A base de type struct A base de tableaux indicés en parallèle
• Le type struct permet de regrouper des #define n 10 x y
informations étroitement liées et float x[n]; 0 0
éventuellement hétérogènes float y[n]; 1 1
#define n 10
struct point <x[i], y[i]> forme un point
{ p i i
0 1 n-1
float x;
float y;
};
struct point p[n]; n-1 n-1

<p[i].x, p[i].y> forme un point


38

LSI 1

La notion de table : annuaire téléphonique


A base de struct A base de tableaux indicés en parallèle
#define n 10 #define n 10
char * nom[n]; /* chaque case est un pointeur vers une chaîne
struct abonne annuaire_tel de caractères */
{ unsigned tel[n];
0
char * nom; 0 nom tel
0
1
unsigned tel; 1
@ ‘a’ ‘l’ ‘i’ ‘\0’
1
};
i
struct abonne annuaire_tel[n]; i
i

n-1
n-1
n-1
39

LSI 1

La notion de table : annuaire téléphonique


A base de struct A base de tableaux indicés en parallèle
#define n 10 … 0 #define n 10
char nom[n][30]; /* chaque case nom[i] est un tableau
struct abonné 0 29

de caractères */
{ unsigned tel[n]; 0 29
char nom[30]; 0

0
tel
nom
unsigned tel; . 1

1

}; .
struct abonné annuaire_tel[n]; . i i
Matrice de caractères
Gaspillage de
l’espace mémoire
n-1 n-1
n-1
40

LSI 1

Recherche séquentielle : Réalisation en C


Données du problème Réalisation en C : Solution 1
# define n 100
• Soit un annuaire téléphonique comportant /* variables globales */
un ensemble de paires <nom, tel> char * nom[n] ;
unsigned tel[n] ;
▫ nom est le nom de l’abonné int recherche_sequentielle(char *x)
▫ tel son numéro /* rend -1 si x n’appartient pas à nom sinon le numéro de tel correspondant
*/
{
unsigned i ;
• On voudrait chercher le numéro de /* pour parcourir la table nom */
téléphone d’un abonné donné for (i=0 ; i<n ; i++)
{
if(strcmp(nom[i],x)==0)
/* issue positive */
• On choisit de représenter l’annuaire par return(tel[i]);
deux tableaux indicés en parallèle }
/* issue négative */
return -1 ;
}
41

LSI 1

Rappel des fonctions strcmp

int strcmp (const char * chaîne1, const char * chaîne2)


Rôle Comparer lexicographiquement chaîne1 et
chaîne 2
chaîne1 Adresse de la première chaîne
chaîne2 Adresse de la deuxième chaîne
Valeur de retour - < 0 : si la chaîne d’adresse chaîne1
arrive avant la chaîne2
- > 0 : si la chaîne d’adresse chaîne1
arrive après la chaîne2
- = 0 : si les deux chaînes sont
identiques
42

LSI 1

Recherche séquentielle : Réalisation en C


Evaluation de la Solution 1 Réalisation en C : Solution 2
#include <string.h>
• L’utilisateur du schéma for n’est pas #define n 10
approprié char * nom[n];
unsigned tel[n] ;
▫ le nombre d’itérations n’est pas connu int recherche_sequentielle(char [])
dés le début /* rend -1 si x n’appartient pas à nom sinon le numéro de tel correspondant */
{
 ceci explique la sortie brutale au sein du unsigned i ;
corps du schéma for /* pour parcourir nom */
i=0 ;
while ((i<n) && (strcmp(x,nom[i]) !=0))
i++;/* pour passer à l’élément suivant */
/* à la sortie de la boucle while :
Il est recommandé d’utiliser ( i>=n) =>échec ou strcmp(x,nom[i])==0 => succès et forcément (i<n) */
le schéma while if(i<n)
return tel[i] ;
else
return -1 ;
}
43

LSI 1

Recherche séquentielle avec sentinelle


Evaluation de la Solution 2 Solution 3 : technique de la sentinelle
• L’expression qui gouverne le schéma while est une • Au lieu de réserver un espace de n éléments
expression composée de la forme p && q
▫ on réserve un espace de N= n+1 éléments
▫ l’ordre d’apparition de p et de q est significatif
 utilisation de && dans un esprit non #define N 11 /* au lieu de 10*/
commutatif • L’élément de position N-1 joue le rôle d’une
i=0 ; sentinelle
while ((i<n)&&(strcmp(x,nom[i]) !=0)
▫ on ne peut pas aller au-delà d’une sentinelle
i++;
• À chaque itération on fait 3 évaluations ▫ à la position N-1, on va mettre l’information
▫ 1ère évaluation : i<n res1 « x » à rechercher dans le tableau « nom »
▫ 2ème évaluation : strcmp(x,nom[i]) !=0 res2 ▫ dans tel[N-1], on va mettre -1
▫ 3ème évaluation : res1 && res2 ▫ « x » est appelé sentinelle

•On souhaite simplifier l’expression composée


•Pour y parvenir, on fait appel à la technique de la sentinelle
44

LSI 1

Recherche séquentielle avec sentinelle


• On recopie l’élément recherché dans la Nème case de la table
▫ il est alors inutile de tester si (i < N) dans la boucle puisqu’on est sûr de trouver l’élément dans la table
▫ si on ne le retrouve pas avant la Nème entrée
 c’est que l’élément n’est pas dans la table
▫ les éléments sont numérotés de 0 à N-1
▫ une place doit être gardée libre en fin du tableau pour l’élément à rechercher

• Dans cette solution une étape d’initialisation du tableau se pose


▫ en effet la partie entre 0 et N-2 sera réservée aux éléments du tableau initial et l’élément N-1 sera réservé pour la
sentinelle
 avec N=n+1

• Dans une structure linéaire ici les tableaux on peut placer un espace supplémentaire (une
sentinelle) soit à droite soit à gauche
▫ dans le cas de la recherche on va placer une sentinelle à droite du tableau
45

LSI 1

Recherche séquentielle avec sentinelle


Pseudo code Réalisation en C
Fonction Recherche_Séquentielle_Sentinelle (x : unsigned Recherche_Séquentielle_Sentinelle (
entier,A: Tab, n : entier) : booleen
Var int x , int A[], unsigned n)
i : entier {
Debut i=0;
i←1
A[n] ← x
A[n-1] = x ;
tant que ( (A[i]<> x)) faire
i ← i+1 while( A[i]!= x ) i++ ;
finfaire
si (i<n) alors
retourner vrai // issue positive if (i<n-1) return 1 ;// issue positive
sinon // i=n else return 0 // issue négative
retourner faux // issue négative
finsi
Fin Recherche_Séquentielle _Sentinelle
}
46

LSI 1

Recherche séquentielle avec sentinelle


Réalisation en C : Solution 3
technique de la sentinelle
Complexité temporelle
#include <string.h>
#define n 11
• l’opération à comptabiliser est la
char *nom[n]; comparaison entre x et l’élément courant
int tel[n]; ▫ strcmp(x,nom[i])
int recherche_sentinelle(char *x)
/* rend -1 si x n’appartient pas à nom sinon le numero de tel • On distingue
correspondant*/
{
▫ cas minimum : une seule comparaison
unsigned i ;  ce cas traduit que x coïncide avec le
/* pour parcourir nom */ premier élément du tableau O(1)
/*garnir la sentinelle*/
nom[n-1]=(char*) malloc (strlen(x)+1) ; ▫ Cas maximum : n comparaisons
strcpy(nom[n-1], x);  x coïncide avec le dernier élément ou x
tel[n-1]=-1 ;
n’appartient pas au tableau O(n)
i=0;
while(strcmp(x,nom[i]) != 0) ▫ Cas moyen : n/2 comparaisons
i++;  O(n/2)
return(tel(i]);
}
47

LSI 1

Rappel des fonctions strcpy

char * strcpy(char* but, const char * source)

but Adresse à laquelle sera recopiée la chaîne


source
source Adresse de la chaîne à recopier source

valeur de retour Adresse de la chaîne but

Aucun contrôle de longueur n’est effectué par cette fonction, il est


donc nécessaire que l’emplacement réservé à but soit suffisant
pour y recevoir la chaîne située à l’adresse source sans oublier le
caractère de fin de chaîne (‘\0’)
48

LSI 1

Recherche séquentielle avec et sans sentinelle


Complexité Solution 2 : sans sentinelle Complexité Solution 3 : avec sentinelle
• complexité spatiale • complexité spatiale
▫ n éléments à stocker ▫ (n+1) éléments à stocker
▫ O(n) ▫ O(n)
• complexité temporelle • complexité temporelle
▫ à chaque itération il y a 3 évaluations ▫ à chaque itération il y a 1 évaluation

•On a pu améliorer la complexité temporelle de la solution 2 moyennant un espace


supplémentaire (1 seul élément)
•La solution 3 consomme moins de temps machine que la solution 2
•On dit que la solution 3 est plus efficace que la solution 2
•On recommande la solution 3 en effet le temps de réponse est plus rapide
•On ne recommande pas la solution 1
49

LSI 1

Recherche dichotomique : Présentation informelle

• On suppose ici que l’on dispose d’un tableau trié par ordre
croissant et qu’on souhaite savoir si un élément fixé (i.e. une
donnée) figure ou non dans la séquence

▫ on peut bien sûr utiliser une recherche séquentielle qui consiste à regarder
successivement, en partant de la gauche du tableau, tous les éléments

▫ néanmoins, il serait plus astucieux d’utiliser une recherche dichotomique


50

LSI 1

Recherche dichotomique : Présentation informelle


▫ L’algorithme de recherche dichotomique (ARD) consiste à comparer l’élément qui se
trouve au centre de la séquence avec l’élément recherché
 si cet élément central est égal à l’élément recherché, c’est terminé (issue positive)
 s’il est supérieur à l’élément recherché
▫ on abandonne la moitié droite de la séquence (correspondant aux éléments plus grands que l’élément
central) et on recommence avec la séquence formée par la moitié gauche (correspondant aux
éléments plus petits que l’élément central) de la séquence initiale
 s’il est inférieur à l’élément recherché
▫ on abandonne la moitié gauche de la séquence (correspondant aux éléments plus petits que l’élément
central) et on recommence avec la séquence formée par la moitié droite (correspondant aux
éléments plus grands que l’élément central) de la séquence initiale

 Et ainsi de suite jusqu’à ce que la séquence restante soit vide (recherche infructueuse ou
issue négative) ou bien avoir trouvé l’élément cherché (recherche fructueuse ou issue
positive)
L’algorithme de recherche dichotomique applique le principe « diviser pour
résoudre » ou encore « diviser pour régner »
51

LSI 1

Recherche dichotomique : Pseudo Code


FONCTION Recherche_Dichotomique (x : entier, A : Tab, n : entier) : booleen
VAR
gauche, droite, milieu : entier
DEBUT
gauche  1
droite  n
tant que (gauche <= droite) faire
milieu  (gauche + droite) div 2
si (x=A[milieu])
alors retourner vrai // issue positive
finsi
si (x < A[milieu] )
alors droite  milieu – 1
sinon gauche  milieu + 1
finsi
finfaire
retourner faux // issue négative
FIN Recherche_Dichotomique
52

LSI 1

Recherche dichotomique : Exemple d’animation


53

LSI 1

Recherche dichotomique : Réalisation en C


Réalisation en C
#include <string.h> do
#define n 100 {
char * nom[n]; m=(g+d)/2 ; /* division entière */
/* nom est trié par ordre alphabétique* / cmp=strcmp(x,nom[m]) ;
if(cmp==0) ;
unsinged tel[n] ;
return tel[m] ; /* issue positive */
int recherche_dichotomique(char *x)
/* soit déplacer g soit déplacer d jamais déplacer les deux à
/*-1 si x n’appartient pas à nom sinon tel correspondant*/ la fois */
{ if(cmp<0) /*x<nom[m]*/
int g,d ; /* sous tableau de recherche */ d=m-1;
int m ; /* indice de l’élément au milieu */ else /*(cmp>0)=> x>nom[m]*/
int comp ;/*résultat de comparaison x et nom[m]*/ g=m+1 ;
}while(g<=d) ;
/*initialisation*/ /* g>d sous tableau vide */
return -1 ; /* issue négative* /
g=0 ;
}
d=n-1 ;
54

LSI 1

Recherche dichotomique : Complexité

• Complexité temporelle
 l’opération à comptabiliser est la comparaison strcmp(x, nom[m]) ?

 Cas minimum ou optimiste (meilleur des cas)


 une seul comparaison, ce qui est traduit par le fait que x coïncide avec nom[0+(n-1)/2]

 Cas maximum ou pessimiste (pire des cas)


 ce cas traduit le fait que x n’appartient pas à nom
▫ à chaque itération, on part d’un problème de taille n et moyennant une
comparaison (strcmp), on passe à sur un problème de taille n/2
▫ le problème initial est divisé en deux sous problèmes disjoints et de taille plus ou moins
égale

 Cas moyen : entre 1 et log2n


55

LSI 1

Recherche dichotomique : Complexité

On note Cn : le nombre de fois où strcmp() est effectuée


Cn= Cn/2+ 1
= Cn/22 + 1+ 1
= Cn/23 + 1+ 1+ 1

= Cn/2i + i

= C1+N = 1+N =1+ log2n On pose n=2N ou N=log2n
avec C1=1 (pour un tableau d’un seul élément)

Ainsi, cet algorithme est en O(log2n)


56

LSI 1

Recherche dichotomique
• Le gain apporté par l’application de l’algorithme de recherche dichotomique sur un tableau
trié peut être illustré par l’exemple suivant
▫ on souhaite effectuer une recherche sur un tableau trié T de taille N=10000
▫ si on applique
 l’algorithme de recherche séquentielle
 la complexité dans le cas moyen est 5000

 l’algorithme de recherche dichotomique


 la complexité le cas moyen est o(log2 10000)/2≈14/2=7

On a donc intérêt à utiliser la recherche dichotomique


parce qu’elle est plus efficace

Vous aimerez peut-être aussi