Introduction à l'algorithmique
Introduction à l'algorithmique
Programmation
algorithmique
[Link] 1/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
[Link] 2/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
Introduction
Introduction
«
I conjecture that there is no good algorithm for the traveling
salesman problem. My reasons are the same as for any
mathematical conjecture: (1) It is a legitimate mathematical
possibility, and (2) I do not know.
»
— Jack Edmonds
Tout comme l'homme, la machine calcule ! Si vous avez déjà ouvert un livre de recettes de cuisine
ou déchiffré un mode d'emploi traduit directement du coréen pour faire fonctionner un
magnétoscope ou un répondeur téléphonique réticent, sans le savoir, vous avez déjà exécuté des
algorithmes. Les algorithmes sont des outils pour la résolution de problèmes. Évaluer leur
efficacité permet de classer ces problèmes selon leur difficulté intrinsèque.
Nous allons dans un premier temps définir précisément ce qu'est un algorithme. Nous présentons
ensuite les outils mathématiques nécessaires à l'évaluation de leur efficacité. Nous proposons une
typologie des problèmes de décision qui s'appuie sur la difficulté calculatoire de leur résolution.
Nous proposons également ce même type de typologie pour les problèmes de recherche.
Algorithme
Un algorithme est une procédure de calcul constituée d'une suite d'instructions, qui prend en
entrée une valeur ou un ensemble de valeurs et qui une fois exécutée correctement, conduit à un
résultat donné : une valeur ou un ensemble de valeur appelé sortie. Un algorithme est un outil de
résolution d'un problème abstrait bien défini. Celui-ci doit énoncer la relation désirée entre
l'entrée et la sortie en des termes généraux mais non-ambigus. Si l'algorithme est correct, la
sortie correspond au résultat désiré. On dit alors que l'algorithme résout le problème posé. Un
algorithme décrit une procédure de calcul spécifique pour établir cette relation. Il peut exister
plusieurs algorithmes candidats pour un problème donné. Il est alors nécessaire de les évaluer.
[Link] 3/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
Un algorithme est dit structuré s'il dispose d'un seul point d'entrée et un seul point de
sortie et peut ainsi être schématisé par un bloc d'instructions avec un début et une fin
(interdiction d'utiliser le branchement explicite GOTO pour entrer n'importe où dans l'algorithme
ou pour en sortir de n'importe où). Cette contrainte a pour but d'améliorer la facilité de
compréhension et d'analyse des algorithmes.
Dans la grande majorité des cas, seul l'ordre de grandeur nous intéresse.
La notion de complexité est très importante en algorithmique. Elle consiste à compter le nombre
d'opérations d'un algorithme en comptant par exemple les additions, les multiplications, les
divisions, les puissances etc... Considérons par exemple un produit de matrices et résonnons d'une
manière simple d'après la formule de base pour calculer la valeur d'un coefficient
Chaque opération effectuée prend un certain temps. Cette durée étant variable selon la machine
utilisée, on ne s'intéressera qu'au nombre d'opérations pour représenter la durée d'exécution d'un
algorithme. On parle alors de complexité en temps. On peut aussi s'intéresser à la quantité de
mémoire nécessaire pour exécuter un algorithme. On parlera alors de complexité en espace.
Efficacité asymptotique
[Link] 4/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
Lorsque la complexité d'un algorithme, en temps ou en espace, est exprimée sous la forme d'un
polynôme où est la taille de l'entrée et les sont des constantes, nous
négligerons non seulement le coefficient constant du premier terme mais également les termes
d'ordre inférieur. On note alors et par abus de langage . Cette
notation est explicitée de manière plus formelle dans la définition suivante.
La complexité d'un algorithme destiné à résoudre un problème ne doit pas être confondue avec la
complexité intrinsèque de ce problème. En effet, on peut concevoir plusieurs algorithmes de
complexités différentes pour résoudre un même problème. Voir Théorie_de_la_complexité_ pour
plus d'information sur la notion de complexité intrinsèque d'un problème algorithmique.
Notation
Nous utiliserons dans la suite de ce livre un formalisme permettant l'abstraction des algorithmes
que nous décrirons, de telle sorte qu'ils soient utilisables quel que soit le langage utilisé. Nous
donnerons l'équivalence en langage C++, en Pascal et en langage assembleur Intel pour chaque
mot clef. Le but n'est pas ici d'apprendre, ou bien de comparer ces différents langages, mais de
fournir des repères, des illustrations au formalisme choisi.
Entier
Réel
Pointeur
Booléen
Caractère
unEntier : Entier
unRéel : Réel
unCaractère : Caractère
unBooléen : Booléen
unPointeur : Pointeur
Pendant l'exécution d'un programme, la valeur associée à chaque variable est stockée en mémoire.
La position de cette valeur dans la mémoire est appelée son adresse. Selon le langage de
programmation utilisé, les adresses peuvent être manipulées comme les autres données (cas de C
et C++), et on parle alors de pointeurs, ou bien les adresses ne sont pas directement manipulables
(cas de Java, de Python, et généralement des langages fonctionnels).
[Link] 5/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
Pour accéder au contenu de la mémoire pointée par une variable de type Pointeur, nous utiliserons
le caractère «*». Ainsi pour accéder au contenu de la variable pointée par le pointeur unPointeur,
on procèdera de la manière suivante :
* unPointeur
En langage C++
int unEntier;
double unRéel;
char unCaractère;
bool unBooléen;
void * unPointeur;
En Pascal
unEntier : INTEGER;
unRéel : REAL;
unCaractère : CHAR;
unBooléen : BOOLEAN;
unPointeur : ^VOID;
En Assembleur Intel
L'assembleur Intel ne prend pas en compte les types de données, mais la taille des données à
réserver dans la mémoire. Ainsi, sur les architectures Intel 32 bits, la taille des données est la
suivante :
Entier : 4 octets ;
Réel : 8 octets ;
Caractère : 1 octet ;
Pointeurs : 4 octets.
En assembleur, la notion de booléen est exprimée par un entier égal (faux) ou différent de zéro
(vrai).
unEntier DD ?
unRéel DQ ?
unPointeur DD ?
Tableaux
t est la variable et N est la taille du tableau. Si i est un entier inférieur à la taille du tableau, t[i]
désigne la valeur de la case i du tableau.
Les types de données composés permettent de rassembler plusieurs variables sous un même nom.
Les variables ainsi rassemblées sont appellées les champs de l'enregistrement. Ils sont définis de la
manière suivante :
unEnregistrement : Enregistrement
unPremierEntier : Entier
unDeuxièmeEntier : Entier
unRéel : Réel
Fin Enregistrement
unEnregistrementInstancié : unEnregistrement
unEnregistrementInstancié.unPremierEntier
Ce qui correspond
En langage C ou C++
En Pascal
TYPE
unEnregistrement=RECORD
unPremierEntier :INTEGER ;
unDeuxiemeEntier :INTEGER ;
unReel :REAL ;
END ;
[Link] 7/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
En Assembleur Intel
unEnregistrement STRUC
unPremierEntier DD
unDeuxiemeEntier DD
unReel DQ
unEnregistrement ENDS
Affectations
uneVariable := uneExpression
Ce qui correspond
En langage C ou C++
uneVariable = uneExpression
En Pascal
uneVariable := uneExpression
En Assembleur Intel
Structure alternative Si
SI condition
// Faire quelque chose
FIN SI
[Link] 8/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
SI condition
// Faire quelque chose
SINON
// Faire autre chose
FIN SI
Ce qui correspond
En langage C ou C++
if (/*condition*/)
{
// Faire quelque chose
}
else
{
// Faire autre chose
}
En Pascal
IF TEST THEN
BEGIN
{Faire quelque chose}
END
ELSE
BEGIN
{Faire autre chose}
ELSE
END ;
En Assembleur Intel
[Link] 9/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
La structure suivant permet d'éviter une suite de Si imbriqués dans le cas fréquent où l'on doit
réaliser des traitements différents en fonction des valeurs d'une variable énumérable (entier).
unEntier : Entier
SUIVANT unEntier
val1 : // faire une chose
val2 : // faire autre chose
val3, val4, val5 : // faire autre chose, ici une énumération de valeurs
val6..val7 : // faire autre chose, ici un intervalle de valeurs
FIN SUIVANT
unEntier : Entier
SUIVANT unEntier
val1 : // faire une chose
val2 : // faire autre chose
val3, val4, val5 : // faire autre chose, ici une énumération de valeurs
val6..val7 : // faire autre chose, ici un intervalle de valeurs
SINON
// encore autre chose
FIN SUIVANT
Par exemple :
choix : entier
afficher menu
lire choix
suivant choix
1 : ajouter
2 : supprimer
3,5,6 : insérer
4 : copier
7..10 : fin := VRAI
sinon:
[Link] 10/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
Cette structure itérative permet de répéter de façon inconditionnelle un nombre de fois connu à
priori un ensemble d'actions (ou instructions).
unEntier : Entier
Par exemple :
i : Entier
Cette structure itérative permet de répéter un ensemble d'instructions tant qu'une condition reste
vraie.
TANTQUE condition
// Faire quelque chose
FIN TANTQUE
Par exemple :
i := 1
TANTQUE i <= MAX ET tab[i] != élémentCherché
[Link] 11/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
i := i + 1
FIN TANTQUE
Remarque : si dès le début la condition est fausse, le bloc d'instruction du tant que n'est jamais
exécuté (test préventif de condition avant toute action).
Cette structure itérative permet de répéter un ensemble d'instructions jusqu'à ce qu'une condition
devienne vrai.
RÉPÉTER
// Faire quelque chose
JUSQU'À condition
Par exemple :
trouvé := FAUX
i := 1
RÉPÉTER
SI tab[i] = élémentCherché ALORS
trouvé := vrai
SINON
i := i + 1
FIN SI
JUSQU'À i > MAX OU trouvé
Remarque : le bloc d'instruction est exécuté une fois de manière inconditionnelle avant
l'évaluation de la condition.
[Link] 12/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
[Link] 13/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
Calcul de np
Algorithme simple
ENTIER resultat
resultat <- 1
pour i de 1 à p
faire
resultat <- resultat * n
finfaire
Cet algorithme est plus compliqué, mais effectue moins d'opérations que le précédent :
ENTIER resultat
resultat <- 1
tantque p > 0
faire
si p ET 1 <> 0 alors # test du bit 0 de p
resultat <- resultat * n
[Link] 14/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
finsi
n <- n * n
p <- p / 2 # division entière ou décalage de bits
finfaire
Chaque bit de p est testé, s'il vaut 1, il faut multiplier le résultat temporaire par . La
relation mathématique entre les puissances est utilisée. Par exemple : .
Donc pour tous les bits de , on a :
Nous avons donc ici deux algorithmes qui calculent le même résultat mais en effectuant des
opérations différentes. Le second algorithme est bien plus rapide que le premier car lorsque
devient très grand, devient négligeable devant . Pour de petites valeurs de , le second
algorithme peut être plus lent.
Dans cet exemple, l'algorithme le plus rapide est aussi le plus compliqué à écrire et à comprendre,
mais ce n'est pas toujours le cas.
Notons que le facteur d'accélération amené par une machine parallèle, c'est-à-dire munie de
plusieurs processeurs, est limité. Par exemple, pour une machine à 64 processeurs, on peut espérer
aller 64 fois plus vite au maximum. Pour un algorithme en et valant 100, le nombre
d'opérations sur une machine séquentielle est de l'ordre de , tandis que sur une machine à 64
processeurs on peut espérer un ordre de soit ou opérations. On voit bien
ici que le nombre de processeurs, forcément limité, n'influence pas forcément la complexité en
temps. Ceci s'explique également par le fait qu'un facteur multiplicatif constant (ici ) est
négligeable devant un carré ou une exponentielle quand la taille du problème devient grande.
[Link] 15/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
Quant aux machines quantiques, qui sont loin d'être exploitables actuellement, leur utilisation
remettrait à plat l'état de l'art en algorithmique et en complexité. Par exemple, pour des problèmes
dont on ne connaît que des algorithmes de complexité en temps exponentielle, on connaît des
algorithmes quantiques de complexité linéaire. Alors qu'il faut actuellement des dizaines d'années
à des machines parallèles surpuissantes pour casser une clé de chiffrement, un ordinateur
quantique mettrait quelques instants.
[Link] 16/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
[Link] 17/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
Maths 1
Calcul de suites
U0=1
Un+1=[Link]+8
Paramètres en entrée : l'entier N
Paramètres en sortie : l'entier U
Spécifications : U doit être égal à UN.
Algorithme :
0/ début suite-1
1/ écrire ("n=")
lire (n)
2/ U<-1
pour i de 1 a (n-1) faire :
U<- 3*U+8
fin pour
3/ fin suite-1
U0=1
Un+1=[Link]+n+4
Paramètres en entrée : l'entier N
Paramètres en sortie : l'entier U
Spécifications : U doit être égal à UN.
Algorithme :
u,n,i : Entier
u := 1
pour i de 0 à n - 1
[Link] 18/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
u := 3*u + i + 4
fin Pour
U0=1
U1=1
Un+2=Un+1+Un
Paramètres en entrée : l'entier N
Paramètres en sortie : l'entier U
Spécifications : U doit être égal à UN.
Algorithme :
u,v,w,n,i : entier
v := 1
w := 1
si u=0 alors
u := w
sinon
si u = 1 alors
u := v
sinon
pour i de 2 à N - 2
u := v+w
w := v
v := u
fin pour
fin si
fin si
U0=1
U1=17
Un+2=(n+4)*Un+1+[Link]+n
Paramètres en entrée : l'entier N
Paramètres en sortie : l'entier U
Spécifications : U doit être égal à UN.
Algorithme :
[Link] 19/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
u,v,w,n,i : Entier
v := 17
w := 1
si u = 0 alors
u := w
sinon
si u := 1 alors
u=v
sinon
pour i de 2 à N - 2
u := (i + 4)*v + 2*w + i
w := v
v := u
fin pour
fin si
fin si
Calcul de somme
n,s,i : Entier
s := 0
pour i de 1 à N
s := s + i
fin pour
Calcul polynomial
Algorithme :
[Link] 20/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
p := 0
pour i de 0 à n
p := p*x + a[n - i]
fin pour
[Link] 21/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
[Link] 22/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
Tableaux
Algorithmes sur les tableaux
Soit
[Link] 23/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
trouve := FAUX
indice := -1
i := 0
tant que non trouve ET i <= N
si t[i] = v alors
trouve := true
indice := i
sinon
i := i+1
finsi
fin tant que
s := 0;
pour i de 1 à N
s := s + t[i]
fin pour
nb := 0
pour i de 1 à N
si t[i] = v alors
nb := nb+1
[Link] 24/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
finsi
fin pour
début
debut <- 0
fin <- n-1
trouve <- faux
tant que debut <= fin et non trouve faire
i <- (debut+fin)÷2
si t[i] = e
alors trouve <- vrai
sinon si t[i] > e
alors fin <- i-1
sinon debut <- i+1
fsi
fsi
ftant
si trouve
alors indice <- i
sinon indice <- -1
fsi
retourne indice
fin
Lexique :
Algorithme d'échange
Algorithme Echange (t : tableau d'entiers ; i,j : entiers) { Echange le contenu des cases i et j dans le
tableau t } Lexique pro : entier Début
pro := t[i]
t[i] := t[j]
[Link] 25/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
t[j] := pro
Fin
Var i, X, c, n: Entier;
tableau t[100]: Entier;
Début
Ecrire("Saisir la borne supérieur du tableau :");
Lire(n);
Pour i := 1 à n Faire
Ecrire("Donner la valeur de l’élément :");
Lire(t[i]);
Fin de Pour
Faire
Pour i := 1 à n-1 Faire
c := 0;
Si t[i] > t[i+1] Alors
X := t[i];
t[i] := t[i+1];
t[i+1] := X;
c := 1;
Fin de Si
Fin de Pour
Tant que (c = 1)
Fin
[Link] 26/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
[Link] 27/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
Tris
Les algorithmes de tri vise à ordonnancer une séquence, en suivant un ordre total. Pour pouvoir
être trié avec ces algorithmes, un ordre doit donc être établi sur les éléments à trier.
Cet ordre est implicite pour des entiers, il peut l'être moins sur des données plus complexes
comme par exemple des nombres flottants ou des textes.
Pour i de 1 à N - 1
//chercher le plus petit entier entre la position i et la fin du
tableau
min := t[i]
indicemin := i
Pour j de i + 1 à N
Si t[j] < min
min := t[j]
indicemin := j
Fin si
Fin pour
// Échanger t[i] et t[indicemin]
temp := t[i]
t[i] := t[indicemin]
t[indicemin] := temp
Fin pour
Complexité en temps:
Tri bulle
Paramètre en entrée/sortie : Un tableau t de N entiers T[1..N];
Spécifications : en sortie t doit être trié du plus petit au plus grand.
[Link] 28/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
repeter
nb := 0
pour i de 1 à N - 1
si t[i] > t[i+1] alors
temp := t[i]
t[i] := t[i+1]
t[i+1] := temp
nb <- nb + 1
fin si
fin pour
jusqu'à nb = 0
Tri linéaire
i ,j ,x :Entiers;
pour i de 1 à n - 1
debut pour
# mémoriser T[i] dans x
x ← T[i];
# décaler vers la droite les éléments de T[0]..T[i-1] qui sont
plus grands que x
j ← i;
tant que j > 0 et T[j - 1] > x
T[j] ← T[j - 1];
j ← j - 1;
fin tant que;
# placer x dans le "trou" que ça a laissé
T[j] ← x;
fin pour; Fin;
Tri rapide
On choisit le pivot de manière aléatoire dans le tableau. Ensuite on inverse le pivot de sa position à
celle du premier élément du tableau (indice 1) puis on fait une comparaison avec tous les éléments
du tableau. S'il y a un élément du tableau qui lui est supérieur, alors il y a échange des éléments.
[Link] 29/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
Cette comparaison s'arrêtera quand l'indice gauche du tableau (ici i) sera plus grand que l'indice
droit du tableau (ici j). Après cet arrêt de la fonction Partitionner, on retourne l'indice j et on
rappel la procédure Tri_rapide
Complexité en espace : En raison des appels récursif, on a besoin d'une pile dont la taille
est en .
Complexité en temps : en moyenne, dans le pire cas.
[Link] 30/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
Tri fusion
Complexité en temps :
Nom anglais : merge sort.
Tri comptage
[Link] 31/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
}
}
Tri-paquet (A) :
n := longueur(A) ;
pour i de 1 à n
faire insérer A[i] dans la liste B[ÎnA[i]°]
pour i de 0 à n-1
faire trier la liste B[I] par le tri insertion
concaténer les listes B[0], B[1], …, B[n-1] dans l’ordre
Tri de Shell
Complexité en temps : la complexité en temps de ce tri dépend de son paramétrage et,
selon les cas, on trouve , , ou par exemple. Voir w:Shellsort,
w:Tri_de_Shell ou The art of Computer Programming volume 3, Donald E. Knuth, Addison-
Wesley.
Notons que les périphériques de stockage sont généralement plus lents que la mémoire vive. Par
ailleurs, autrefois le support externe de référence était la bande magnétique, avec pour résultat que
le temps d'accès à une donnée dépend de sa position sur la bande, alors qu'en mémoire vive, le
temps d'accès aux données ne dépend pas de leur emplacement (si l'on fait abstraction des
questions de mémoire tampon).
[Link] 32/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
[Link] 33/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
[Link] 34/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
[Link] 35/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
Une liste simplement chaînée est une structure de données pouvant contenir plusieurs éléments.
Chaque élément possède un pointeur vers l'élément suivant. La liste est un pointeur vers le
premier élément de la liste. Le dernier élément pointe vers une adresse spécifique (notée NIL)
pour signifier la fin de la liste.
La clef d'un élément est d'un type quelconque. On peut ajouter des informations utiles aux
éléments.
ELEMENT : ENREGISTREMENT
CLEF
SUIVANT : ELEMENT
FIN ENREGISTREMENT
LISTE : ENREGISTREMENT
TETE : ELEMENT
FIN ENREGISTREMENT
Recherche d'un élément ayant une clé CLEF dans une liste
Complexité : O(N)
Complexité : O(1)
[Link] 36/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
Complexité : O(N)
Voici donc un exemple d'algorithme utilisant la récursion, il s'agit de rechercher un élément dans
une liste, comme plus haut.
Recherche d'un élément ayant une clé CLEF dans une liste (version récursive)
Complexité en temps: O(N). Complexité en espace : O(N) ou O(1) selon le support d'exécution.
On notera que dans cet exemple on ne trouve ni affectation (ou assignation), ni séquence
(succession inconditionnelle de deux instructions). Il s'agit donc bien d'un algorithme fonctionnel.
[Link] 37/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
Selon le langage et le compilateur utilisé pour réaliser cet algorithme, les appels récursifs successifs
seront stockés ou non en mémoire. On parle de pile d'appels récursifs. Dans le cas où le support
d'exécution (c'est à dire l'interprète ou le code compilé) utilise une pile d'appels récursifs pour
exécuter la fonction RECH_REC, la complexité en espace sera O(N), car pour chaque élément de la
liste, on devra stocker en mémoire, sur la pile, l'information sur l'appel en cours. Dans le second
cas, où le compilateur est capable de générer du code qui utilise un espace limité sur la pile, la
complexité en espace sera O(1), comme pour la version itérative. À titre d'exemple, le compilateur
GCC est capable de compiler certaines fonctions récursives écrites en C pour qu'elles utilisent un
espace constant sur la pile, alors que l'interprète standard du langage Python empile
systématiquement les appels récursifs.
Insertion
Complexité O(1)
Complexité : O(1)
Complexité : O(N)
[Link] 38/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
Suppression
Complexité : O(N)
[Link] 39/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
[Link] 40/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
ELEMENT : ENREGISTREMENT
CLEF
SUIVANT : ELEMENT
PRECEDENT : ELEMENT
FIN ENREGISTREMENT
LISTE : ENREGISTREMENT
TETE : ELEMENT
QUEUE : ELEMENT
FIN ENREGISTREMENT
Recherche d'un élément ayant une clé CLEF dans une liste
[Link] 41/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
Complexité : O(1)
Insertion
Complexité O(1)
Complexité : O(1)
[Link] 42/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
FIN SI
FIN FONCTION
Complexité : O(1)
Suppression
Complexité : O(1)
[Link] 43/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
FIN SI
FIN FONCTION
[Link] 44/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
[Link] 45/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
Arbres
Un arbre est une structure de données hiérarchique sans cycle.
Principes
Un arbre est constitué de nœuds. Chaque nœud contient lui-même un ensemble de nœuds "fils"
(tableau ou liste selon l'implémentation).
Le premier nœud sans père, père de tous les autres est nommé "racine de l'arbre". Généralement,
seul le nœud père est conservé dans une variable, car on peut obtenir les autres nœuds en
parcourant l'arbre.
Les parcours en largeur sont plus difficiles à réaliser car, en l'absence de liens entre les nœuds d'un
même niveau dans la structure de données, on utilise généralement une file pour stocker
temporairement les nœuds à traiter dans l'ordre approprié.
Intérêt
Certaines données présentent naturellement une structure d'arbre, par exemple les arbres de
syntaxe dans un compilateur. Mais l'usage des arbres ne se limite pas à ces cas : ils sont
notamment utilisés pour stocker des données de manière à accélérer leur temps d'accès par
rapport au stockage dans un taleau ou dans une liste (complexité en temps logarithmique contre
complexité en temps linéaire).
Le classement d'une série de données avec un arbre permet des recherches en log(N) si l'arbre est
trié et « équilibré » (si dans tout l'arbre, pour 2 branches voisines, on a soit une longueur égale,
soit une différence de longueur de 1 au maximum).
Il existe des algorithmes peu coûteux pour garder un arbre « équilibré » sur insertion ou
suppression d'un élément.
Exemple :
Si chaque nœud a 2 fils, un arbre équilibré de 63 éléments aura une profondeur de seulement 6 :
[Link] 46/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
Algorithmes
Parcours en profondeur
Parcours préfixe
si A ‡ nil /* condition */
fin si
fin
Parcours infixe
Parcours en largeur
Récupérée de « [Link]
title=Programmation_algorithmique/Version_imprimable&oldid=639939 »
[Link] 47/48
19/09/2023 21:55 Programmation algorithmique/Version imprimable — Wikilivres
Les textes sont disponibles sous licence Creative Commons attribution partage à l’identique ; d’autres termes peuvent
s’appliquer.
Voyez les termes d’utilisation pour plus de détails.
[Link] 48/48