Algorithmique

1 805 vues

Publié le

Université Ibn Tofail
Faculté des Sciences
Département d'informatique
Cours Algorithmique SMI/SMA S2
2014-2015
Cours d'introduction à l'algorithmique

Publié dans : Formation
0 commentaire
0 j’aime
Statistiques
Remarques
  • Soyez le premier à commenter

  • Soyez le premier à aimer ceci

Aucun téléchargement
Vues
Nombre de vues
1 805
Sur SlideShare
0
Issues des intégrations
0
Intégrations
4
Actions
Partages
0
Téléchargements
71
Commentaires
0
J’aime
0
Intégrations 0
Aucune incorporation

Aucune remarque pour cette diapositive

Algorithmique

  1. 1. Université Ibn Tofail Faculté des Sciences Département d’Informatique Kénitra SMI-SMA ALGORITHMIQUE A. EL HARRAJ 2014-2015
  2. 2. i Sommaire Sommaire ................................................................................................................................................. i Introduction............................................................................................................................................. 1 Définition et signification .................................................................................................................... 2 Algorithme en informatique................................................................................................................ 2 1. Rappel sur la structure d’un ordinateur.................................................................................. 2 2. Langages de programmation................................................................................................... 3 3. Etapes de réalisation d’un programme................................................................................... 4 Algorithmique et Programmation....................................................................................................... 5 1. Elaboration d’un algorithme ................................................................................................... 5 2. Représentation d’un algorithme............................................................................................. 5 Eléments de base de l’algorithme........................................................................................................... 6 Structure générale d’un algorithme.................................................................................................... 7 Les variables ........................................................................................................................................ 7 1. Notion de variable................................................................................................................... 7 2. Identificateurs ......................................................................................................................... 9 3. Types et valeurs..................................................................................................................... 10 4. Affectation............................................................................................................................. 10 Expressions et opérateurs................................................................................................................. 12 Entrées/Sorties.................................................................................................................................. 13 Les structures alternatives ................................................................................................................ 14 1. L'instruction SI....................................................................................................................... 14 2. L'instruction Selon................................................................................................................. 16 Les structures itératives .................................................................................................................... 18 1. Instruction TantQue : ............................................................................................................ 18 2. Instruction Répéter ............................................................................................................... 19 3. Instruction Pour..................................................................................................................... 20 4. Choix de la boucle. ................................................................................................................ 22 Tableaux ................................................................................................................................................ 23 Définition........................................................................................................................................... 24 Algorithmes de Lecture/Ecriture....................................................................................................... 25 Algorithmes de Recherche ................................................................................................................ 25 Algorithmes de Tri............................................................................................................................. 28
  3. 3. ii 1. Tri par sélection..................................................................................................................... 28 2. Tri par insertion..................................................................................................................... 30 3. Tri à bulles ............................................................................................................................. 31 Chaines de caractères et Tableaux.................................................................................................... 32 Tableaux à deux dimensions ............................................................................................................. 34 Fonctions et Procédures........................................................................................................................ 36 Principe.............................................................................................................................................. 37 Les fonctions...................................................................................................................................... 38 1. Définition............................................................................................................................... 38 2. Appel d'une fonction............................................................................................................. 39 Les procédures .................................................................................................................................. 41 Transmission des paramètres ........................................................................................................... 42 Fonctions sur les tableaux................................................................................................................. 45 Récursivité......................................................................................................................................... 46 Exercices................................................................................................................................................ 47 Série 1................................................................................................................................................ 48 Série 2................................................................................................................................................ 49 Série 3................................................................................................................................................ 50 Série 4................................................................................................................................................ 51 Série 5................................................................................................................................................ 52 Annexe................................................................................................................................................... 60 Table ASCII......................................................................................................................................... 61
  4. 4. Introduction
  5. 5. 2 Définition et signification • Un algorithme est une description détaillée d’une suite d’actions nécessaires pour réaliser une tache (résoudre un problème). Par exemple, la description de la procédure à suivre pour : - résoudre une équation - préparer un repas - conduire une voiture, un avion, … - Aller d’une ville à une autre - … • Ces procédures sont généralement formulées sous forme d’une suite d’instructions à suivre pour obtenir le résultat souhaité : - mode d’emploi. - recette de cuisine. - itinéraire routier. - … Algorithme en informatique 1. Rappel sur la structure d’un ordinateur Un ordinateur est une machine automatique qui permet de traiter l’information. Il est essentiellement composé de : • Unité Centrale (UC) : formée par : - Un processeur (Unité de commande, Unité de traitement, …) qui est le cœur de l’UC. Son rôle est d’effectuer les calculs et d’assurer la communication entre les différents composants - Mémoire : permet de stocker l’information. • Les périphériques de communication avec l’utilisateur et d’extensions. On distingue : - les périphériques d’entrées pour saisir l’information (Clavier, souris, …) - les périphériques de sortie pour afficher les résultats (écran, imprimantes, enceintes, …) Périphériques Unité Centrale Processeur Mémoire Unités de stockage Unités d’Entrée Unités de Sortie
  6. 6. 3 - Les périphériques de stockage pour archiver l’information et qui jouent aussi les rôles des périphériques d’Entrée/Sortie • Pour effectuer une tache donnée, les instructions et les données pour la réalisation de cette tache sont placées en mémoire, et le processeur commence à exécuter ces instructions l’une après l’autre dans un ordre bien précis, et en cas de besoin, il accède à la mémoire pour lire ou écrire une donnée ou communique avec les périphériques pour recevoir une information ou envoyer un résultat. • L’ensemble des instructions et des données nécessaires pour réaliser une tache forment une entité dite Programme ou Application. Un programme est donc une suite d’instructions ordonnées (algorithme) et des données : Programme = Données + Algorithme. On dit que l’ordinateur exécute un programme lorsqu’il est entrain de réaliser la tache correspondante. 2. Langages de programmation Les composants d’un ordinateur sont essentiellement formés par des ensembles de composantes électroniques à deux états (notés 0 et 1), par ailleurs les informations que peut manipuler un ordinateur sont en binaire : • le processeur effectue des opérations élémentaires sur les binaires (addition, multiplication, opérations logique, …) • la mémoire stocke les données binaires dans des cellules regroupées en blocs de 8, 16, 32 …. Ces blocs sont numérotés pour faciliter l’accès (ce numéro est dit adresse mémoire). L’instruction, que peut exécuter un processeur, doit être conforme à un code binaire compréhensible par le processeur. Chaque famille de processeurs possède un ensemble de codes correspondants aux opérations que le processeur peut réaliser. Cet ensemble de codes est dit Langage machine. La difficulté de manipulation du langage machine a amené les intéressés du domaine à chercher un langage plus maniable, qui sera ensuite convertit en langage machine. Ce qui a donné naissance à un langage symbolique : Assembleur. Mais, ce langage s’avère inefficace pour réaliser des taches complexes. Ce qui a conduit les chercheurs à trouver des langages plus évolués tel que Basic, Pascal, C, … Ces langages utilisent des mots plus clairs et plus significatifs : a = 20 b= a+20 if(a>2) then c=a+1 … Traducteur 01011010... 10110101... ... Langage Machine ADD A, 5 MOV C, 12 ... Assembleur
  7. 7. 4 En plus, la suite d’instructions, constituant un programme, est écrite dans un ou plusieurs fichiers textes constituant le code source. Ce code source est ensuite convertit en langage machine. La conversion se fait à l’aide d’un programme: - Compilateur : qui convertit tout le code source pour former un code en langage machine. - Interpréteur : qui traduit et exécute les instructions du code source en même temps. De nos jours, d’autres langages et techniques sont utilisés, comme par exemple Java ou Python qui utilisent au même temps un compilateur et un interpréteur pour exécuter leurs codes sources, ce qui permet la portabilité des programmes entre différentes machines. Enfin, notons que pour que l’ordinateur exécute bien un programme, qu’il soit écrit dans un langage ou un autre, il faut qu’il soit exact. Autrement dit, il faut qu’il décrive sans ambigüité les instructions à exécuter et l’ordre dans lequel elles seront exécutées. 3. Etapes de réalisation d’un programme • L’informatisation d’un processus commence par la spécification du problème (A partir de l’énoncé du problème trouver ce qu’on a et ce qu’on souhaite réaliser) Cette spécification est formulée sous forme d’un Cahier de charges. Un cahier de charges décrit éventuellement tous les données du problème : les données existantes, ce qu’on veut obtenir de ces données et par quel moyen. • La deuxième étape est l’analyse de cette spécification (phase d’analyse). Dans cette phase on étudie les données (quelles sont les données connues qui serviront d’entrée et quelles sont celles à retrouver en sortie) et les traitements à effectuer sur ces données pour répondre au problème posé. • La troisième étape est l’informatisation : c’est la phase de réalisation du programme. Peut-on écrire les programmes directement en un langage donné ? Quels sont les avantages et les inconvénients ? L’inconvénient réside dans le fait qu’en plus la difficulté du problème on y ajoute celle de l’utilisation du langage (syntaxe, types d’instructions,…). Donc, la manière la plus efficace est d’écrire les étapes nécessaires pour la résolution du problème dans un langage clair et simple (ce qu’on appelle Algorithme) avant de le traduire en langage de programmation (c'est-à-dire en algorithme codé). De ce fait l’étape de l’élaboration des algorithmes pour le développement en informatique s’avère plus qu’utile, puisqu’elle permet de cerner les difficultés de résolution des problèmes indépendamment des langages de programmation. Elle offre aussi au programmeur la possibilité d’utiliser son propre langage pour décrire les opérations et leur enchainement pour informatiser un processus. Spécification Analyse Traduction Compilation Tests, modifications,… Enoncé du problème Cahier des charges Algorithme Codes sources Programme exécutable
  8. 8. 5 Algorithmique et Programmation 1. Elaboration d’un algorithme Un algorithme en informatique est donc la description complète et détaillé des instructions, et leur ordonnancement, nécessaires pour obtenir un résultat donné. Un algorithme doit être donc : • exacte : produit un résultat juste à partir des données exactes • efficace : se produit en un temps acceptable et n’utilise pas trop la mémoire • clair : compréhensible par d’autres personnes • général : traite le plus grand nombre possible des cas. D’autre part, un algorithme est fait pour être traduit en langage de programmation, donc il ne doit contenir que les éléments de base de la programmation : - opérations basique sur les données (addition, soustraction, …) - l’utilisation des variables pour la manipulation des données (affectation, …) - lecture et écriture - les tests - les boucles 2. Représentation d’un algorithme Les deux méthodes de base utilisées pour représenter un algorithme sont : • Organigramme : représentation graphique (rectangles, losanges, cercles,…), donnant une vue d’ensemble sur l’algorithme. Cette représentation est inefficace lorsqu’il s’agit d’un algorithme grand ou compliqué • Pseudo-code : représentation textuelle avec des conventions assez proches de celles utilisées par les langages de programmation. Avec l’évolution de l’informatique, d’autres formes de représentation sont apparues, notamment l’UML (Unified Modeling Language) utilisé pour une programmation plus évoluée (Programmation objet, Programmation événementielle, …).
  9. 9. Eléments de base de l’algorithme
  10. 10. 7 Structure générale d’un algorithme Un algorithme doit être traduit en langage de programmation, lisible, clair et compréhensible par un large public (et non seulement par son auteur). Il s’ensuit, qu’on doit utiliser certaines conventions pour écrire et présenter un algorithme. Donc, un algorithme doit - avoir un nom qui décrit plus ou moins la tache qu’il est sensé réaliser. - mentionner le début et la fin des instructions. - utiliser des noms significatifs pour décrire les actions et les données. - utiliser éventuellement des commentaires pour détailler certaines instructions La présentation conventionnelle la plus utilisée et la plus proche des langages de programmation est : Algorithme : nom_de_l_algorithme Début instruction1 instruction2 ... Fin. NB : Les mots en gras sont des mots clés, ils sont choisis par convention et ne changent pas. L’utilisation de l’indentation (c'est-à-dire : les instructions du même niveau sont écrites sur la même colonne) assure la clarté des algorithmes. Pour assurer plus la clarté des algorithmes, on peut insérer des commentaires dans l’algorithme, pour décrire par exemple la fonction principale de l’algorithme ou le rôle d’une instruction. Les commentaires sont dans la plus part des langages sont écrits entre /* et */. Exemple 2.1 Ecrire("Bonjour") AlaLigne /* saut de ligne */ Fin. : /* cet algorithme permet d’afficher Bonjour */ Algorithme : affiche Début Les variables 1. Notion de variable • La solution, de la plus part des problèmes, nécessite la représentation des données par des symboles : ces symboles représentent au fait les données variables du problème. Exemple : Ecrire un algorithme qui permet de calculer le prix total d’une quantité d’un produit, connaissant le prix unitaire hors taxes, le taux de la TVA et la quantité du produit en question.
  11. 11. 8 La solution parait difficile sans l’utilisation de symboles pour représenter les données du problème. Mais, en notant, par exemple : - pu : prix unitaire - qt : la quantité - tva : taux de la tva - prix_ttc : prix total la solution devient claire : 1. lire les données et les associées aux symboles correspondants (pu, qt et tva) 2. calculer prix_ttc = pu*qt*(1+tva). 3. afficher ou écrire le résultat (prix_ttc). • D’autre part, dans un programme, on est dans la majorité des cas amené à stocker des données. Ces données peuvent être : - des entrées : fournies par l’utilisateur ou lues à partir d’une unité de stockage… - des sorties : résultats à écrire ou à afficher. - des données intermédiaires : les résultats de certaines opérations ou actions que le programme utilisera ultérieurement. • Au niveau du fonctionnement de l’ordinateur, on a vu que les données d’un programme sont placées en mémoire en binaire et chaque donnée est repérée par le numéro du bloc mémoire qu’elle occupe (dit adresse mémoire). Donc, l’accès en lecture ou en écriture à une donnée nécessite la connaissance de l’adresse mémoire et la quantité de cellules qu’occupe la donnée. Le codage en binaire utilisé pour repérer une donnée diffère selon le type de la donnée (caractère, entier, réel, …). Un programme en langage machine doit donc gérer les adresses mémoire, le nombre de cellules et le codage de chacune des données qu’il utilise. Les langages de programmation évoluées ont facilité la tache aux programmeurs, en leur offrant la possibilité d’utiliser des variables, autrement dit, des noms pour représenter les données sans s’occuper ni de leurs emplacements en mémoire ni de la manière dont ils sont codées, à condition que le programme déclare, au préalable, les noms des variables qu’il va utiliser, ainsi que leurs types, pour connaitre la quantité de mémoire qu’occupera ce programme. Pour ce, les langages de programmation utilisent ce qu’on appelle des variables. Une variable est donc une entité qui a : - un identificateur qui est le nom qui permet de la repérer. - une valeur qui peut être ou non modifiée au cours du déroulement du programme. - un type pour designer la nature de l’information que peut contenir la variable (nombre, texte, caractère, suite de nombres…). - une adresse mémoire pour connaitre où elle se trouve (son adresse). • Le programmeur fournit le nom, le type et la valeur et le langage de programmation s'occupe de l'association des différents caractéristiques de la dite variable, notamment de l'adresse mémoire. (Le langage C offre la possibilité d'utiliser l'adresse mémoire via des pointeurs)
  12. 12. 9 • D’autre part, certains de ces langages offrent aussi la possibilité de mentionner si une variable du programme ne sera pas modifiée au cours de l’exécution. Ce type de variables est traité différemment et elles sont dites des constantes. • Il s’ensuit, alors, que dans un algorithme, on doit déclarer les variables, et éventuellement les constantes, que notre algorithme utilisera en spécifiant pour chaque variable un identificateur (le nom) et le type. Dans la structure générale d’un algorithme ne devrons donc ajouter une partie de déclarations : Algorithme : nom_de_l_algorithme Var nom_variable : type_variable Const nom_constante = valeur_constante Début instruction1 instruction2 ... Fin. Les mots Var et Const sont des mots clés conventionnels et sont utilisés pour déclarer une variable ou une constante. - L’identificateur de la variable est suivi du symbole : et du type de la variable. - le nom de la constante est suivi par le symbole = et de la valeur de cette constante. Exemple 2.2 ... ... Fin. : /* Calcul du prix TTC */ Algorithme : calcul_prix_ttc Var pu, prix_ttc : Réel Var qt : Entier Const tva = 0.2 Début 2. Identificateurs • Un identificateur est le nom donné à une entité, dans un algorithme (ou dans un code source d'un langage de programmation). Comme par exemple le nom de l'algorithme ou le nom d'une variable ou d'une constante. • Les langages de programmation exigent certaines règles à respecter pour le choix des identificateurs. La plupart de ces règles sont communes à tous les langages. En algorithmique, donc, on doit suivre aussi certaines de ces règles, et surtout les plus importantes. A savoir :  un identificateur ne doit pas contenir d'espaces. En nommant une variable a b, on ne sera pas s'il s'agit d'une variable ou de deux variables.  un identificateur doit commencer par une lettre :
  13. 13. 10 ab1 ou a1b sont valides 1ab est invalide. Comment lire l'expression : 2+1ab (3 suivi de ab ou 2 plus la variable 1ab) ?  un identificateur ne doit contenir que des lettres, des chiffres et le tiret de soulignement (_) : ab_1 est valide a&b est invalide (peut s'agir d'une opération) "SMI" est invalide (c'est une chaine de caractères).  un identificateur ne doit pas être un mot clé (mot réservé): Algorithme ou Fin sont invalides • Notons qu'en algorithmique, nous ne tiendrons pas compte de la règle du respect de la casse (Différence entre majuscule et minuscule), exigée par certains langages de programmation. • Enfin, signalons que le choix d'identificateurs significatifs, qui décrivent en quelque sorte l'entité qu'il représente modifie considérablement la lisibilité de l'algorithme. 3. Types et valeurs • Le type d’une variable désigne la nature des données que peut représenter cette variable. • La valeur d’une variable peut être n’importe quelle valeur conforme au type de cette variable. Le tableau suivant regroupe les types communément utilisés par la plupart des langages de programmation : Type Valeur Exemple Entier les entiers relatifs 15, -30, … Réel les réels 13.5, 0.5e3, … Booléen VRAI ou FAUX Caractère les lettes, chiffre, symbole entre apostrophes 'a', 'B', '5', '%' Chaine les chaines de caractères entre guillemets "Bonjour", "les 3 singes", … • Certains langages développent plus les types Entier et Réel (Byte, Entier signé, Entier non signé, Entier court, Entier long, Réel simple précision, Réel double précision) pour être conformes aux conventions de codage et pour être précis sur la quantité de mémoire utilisée par le stockage des variables (ce qui permet d'économiser la mémoire). Par ailleurs, les nombres utilisés doivent être dans une plage de valeurs bien précise, qui dépend du langage, de la machine et du système d'exploitation qui gère la machine. Généralement, en algorithmique, on ne tient pas compte des ces considérations. 4. Affectation • L'affectation d'une variable consiste à donner ou à associer une valeur à une variable. • En algorithmique, on utilise le signe '←' pour affecter une valeur à une variable.
  14. 14. 11 Exemples • La variable et la valeur dans une affectation doivent être de même type. : i ← 0 j ← i+15 x ← 1.5 c ← 'A' ch ← "Bonjour" Var i : Entier ... i ← "SMI" /* Erreur */ • La notion de variable, nous montre qu'une variable désigne une entité caractérisée par son nom, sa valeur son type et son emplacement mémoire. Ce qui nous permet donc de modifier le contenu de cette entité. On peut alors écrire des affectations de type : i ← i+15 /* ajouter 15 à la valeur contenue dans i*/ Remarques  La plupart des langages de programmation utilise le signe = pour l'affectation, d'autres utilisent le symbole :=. : En cas d'utilisation du signe =, il faut noter : - a=b (c'est-à-dire a←b) est différent de b=a (c'est-à-dire b←a). - a=a+1 a un sens (c'est-à-dire a←a+1)  Certains langages donnent des valeurs par défaut à certaines variables déclarées. De ce fait, il est conseillé d'initialiser une variable avant de l'utiliser (initialiser : lui donner une valeur au début). Exercice : Donner les valeurs des variables a et b, après l'exécution de chacun des algorithmes suivants. Conclure. Algorithme : algo_test_01 Var a,b:Entier Début a ← 5 b ← 7 a ← b b ← a Fin. Algorithme : algo_test_02 Var a,b:Entier Début a ← 5 b ← 7 a ← a+b b ← a-b a ← a-b Fin.
  15. 15. 12 Expressions et opérateurs • Une expression, en informatique, est une suite de valeurs et de symboles représentant un calcul à faire. Elle peut être : - une valeur - une variable - un ensemble de valeurs et/ou de variables reliées entre eux par des opérateurs. Exemples • Un opérateur est un symbole qui représente une opération et qui selon le type des données (opérandes) qu'il relie peut être un opérateur arithmétique, de comparaison ou logique. : 5 a + 1 3 – 7 * b Les opérateurs que nous utiliserons en pseudo-langage sont :  Opérateurs arithmétiques : + addition - soustraction * multiplication / division % modulo ^ puissance  Opérateurs de comparaison : = ≠ < ≤ > ≥  Opérateurs logiques : NON ET OU • Toute expression a une valeur qui est le résultat de l'évaluation des opérations qu'elle contient. 15 + 7 /* vaut 21 */ 5 > 10 /* vaut FAUX */ ((7 % 2) = 1) OU FAUX /* vaut VRAI */ "SMI" /* vaut "SMI" */ • L'évaluation d'une expression se fait en tenant compte des priorités des opérateurs. 2+3*5 /* vaut 17 */ • L'utilisation des parenthèses dans une expression permet de préciser l'ordre des opérations (les parenthèses ont la priorité la plus élevée). (2+3)*5 /* vaut 25 */ • Si les opérateurs d'une expression ont la même priorité, alors le calcul se fait de gauche à droite (associativité à gauche) : 11+7+15 /* se calcule comme (11 + 7) + 5*/
  16. 16. 13 Priorités des opérateurs 1. : () 2. ^ 3. * / % 4. + - 5. < ≤ > ≥ 6. = ≠ 7. NON 8. ET OU 9. ← Remarques • Notons, que des langages de programmation, utilisent d'autres symboles pour représenter les opérateurs cités ici. Par exemple, en C : : Pseudo-langage langage C ← = = == NON ! • Certains langages définissent d'autres opérateurs, comme par exemples des opérateurs sur les chaines de caractères (& pour la concaténation), des opérateurs de gestion de mémoire, etc. • Enfin, notons que, les langages de programmation évolués définissent, d'une manière claire dans leurs manuels de référence, tous les opérateurs dont ils disposent en précisant leurs priorités et leurs associativités. Entrées/Sorties • Les instructions d'entrée/sortie permettent au programme de communiquer avec l'utilisateur. • En pseudo-code, nous utiliserons les mots clés Lire et Ecrire pour désigner respectivement les instructions d'entrée et de sortie. • L'instruction Lire permet de lire une donnée : Lire(var) permet de lire une valeur et de l'associer à la variable var. Pour un programme exécutable, la saisie de la valeur se fait généralement à partir du clavier. Et cette instruction arrête le programme jusqu'à ce que la valeur saisie soit validée avec la touche ENTREE. • L'instruction ECRIRE permet d'envoyer un message vers la sortie (qui généralement l'écran) Ecrire(expr1, expr2,...) permet d'envoyer vers la sortie, dans l'ordre, les valeurs des expressions expr1, expr2, …
  17. 17. 14 expr1, expr2, ... sont des expressions quelconques (variable, nombre, chaine de caractères, …). Exemple2.3 Les structures alternatives : Ecrire un algorithme qui permet de lire deux entiers et qui affiche leur produit. Algorithme : produit Var a,b:Entier Début Ecrire("entrer un nombre entier : ") Lire(a) Ecrire("entrer un autre nombre entier : ") Lire(b) Ecrire("Le produit de ", a, " par ", b, " est ", a*b) Fin. • Une structure alternative (ou conditionnelle) est une structure dans laquelle une suite d'instructions n'est exécutées que si une condition donnée est satisfaite. • On distingue deux instructions permettant de réaliser une structure conditionnelle : Si et Selon. 1. L'instruction SI La syntaxe de l'instruction SI en pseudo-code est : Si (exp_condition) Alors séquence_1 Sinon séquence_2 Finsi. où : - exp_condition est une expression de type booléen (sa valeur est VRAI ou FAUX). Elle doit être entre parenthèses. - séquence_1 et séquence_2 sont des suites d'instructions. Cette instruction permet d'exécuter sequence_1 si la valeur de exp_condition est VRAI, sinon sequence_2 sera exécutée. Exemple 2.4 : Ecrire un algorithme qui permet d'afficher la valeur absolue d'un entier donnée. Algorithme : valeur_absolue_1 Var n:Entier Début Ecrire("entrer un nombre entier : ") Lire(n) Si ( n > 0 ) Alors Ecrire("la valeur absolue de ", n " est ", n) Sinon Ecrire("la valeur absolue de ", n " est ", -n) Finsi
  18. 18. 15 Fin. • La partie Sinon d'une instruction Si est facultative. La forme la plus simple d'une instruction Si est : Si (exp_condition) Alors séquence Finsi. si exp_condition est VRAI, la suite d'instruction séquence est exécutée, sinon rien ne se passe. Exemple 2.5 • L'expression conditionnelle qui sert de test dans une instruction Si peut être n'importe quelle expression boolienne et particulièrement une expression composée. : Améliorer l'algorithme précédent (valeur_absolue_1), de telle sorte qu'il calcule la valeur absolue du nombre saisi avant de l'afficher. Algorithme : valeur_absolue_2 Var n,n_absolue:Entier Début Ecrire("entrer un nombre entier : ") Lire(n) n_absolue ← n Si ( n < 0 ) Alors n_absolue ← -n Finsi Ecrire("la valeur absolue de ", n " est ", n_absolue) Fin. Exemple 2.6 • Les séquences d'instructions présentes dans une instruction Si peuvent contenir d'autres instructions Si. Dans ce cas on parle d'instructions Si imbriquées. : Ecrire un algorithme qui permet de tester si 3 entiers saisis son ordonnés (du plus petit au plus grand) ou non. Algorithme : entiers_ordonnés Var n1,n2,n3:Entier Début Ecrire("entrer 3 nombres entiers : ") Lire(n1) Lire(n2) Lire(n3) Si (( n1 ≤ n2 ) ET (n2 ≤ n3)) Alors Ecrire("les 3 nombres sont ordonnés") Sinon Ecrire("les 3 nombres ne sont pas ordonnés") Finsi Fin. Exemple 2.7 : Ecrire un algorithme qui permet de tester si un nombre est strictement positif, strictement négatif ou nul.
  19. 19. 16 Algorithme : signe_nombre_1 Var x:Réel Début Ecrire("Donnez un nombre : ") Lire(x) Si (x < 0) Alors Ecrire(x, " est strictement négatif") Sinon Si (x = 0 ) Alors Ecrire(x, " est strictement positif") Sinon Ecrire(x, " est nul") Finsi Finsi Fin. Exercice 2. L'instruction Selon : Ecrire un algorithme qui lit 3 entiers et les affiche dans l'ordre croissant. • L'instruction Selon permet d'exécuter une séquence d'instructions parmi d'autres selon la valeur d'expression. La syntaxe de l'instruction Selon en pseudo-code est : Selon expr Faire Cas val_1 : séquence_1 Cas val_2 : séquence_2 ... Autrement : séquence_autre FinSelon où : - expr : est une expression dont la valeur est soit un entier soit un caractère. - val_1, val_2, ... : sont des valeurs de même type que expr. - séquence_1, séquence_2, … et séquence_autre sont des suites d'instructions. Cette instruction permet de comparer la valeur expr avec val_1, val_2,… dans l'ordre et si une valeur correspond alors la séquence correspondante est exécutée. Sinon (aucune valeur de la liste des cas ne correspond) alors séquence_autre est exécutée. Exemple 2.8 : Ecrire un algorithme qui lit le premier caractère en majuscule d'une couleur et affiche la couleur (par exemple il lit R et affiche Rouge). Les seules couleurs que connait l'algorithme sont : Rouge, Vert, Bleu, Jaune. Si le caractère lu ne correspond à aucune couleur, l'algorithme affiche "couleur inconnue". Algorithme : couleurs_1 Var c:Caractere Début Ecrire("Entrer une lettre en majuscule : ") Lire(c)
  20. 20. 17 Selon c Faire Cas 'R' : Ecrire("Rouge") Cas 'V' : Ecrire("Vert") Cas 'B' : Ecrire("Bleu") Cas 'J' : Ecrire("Jaune") Autrement : Ecrire("Inconnue") Finselon Fin. • La partie Autrement de l'instruction Selon est facultative, mais conseillée. En l'absence de cette partie, si aucune valeur ne correspond, l'instruction Selon n'exécutera aucune instruction. • Dans le cas où on veut exécuter une même séquence pour plusieurs valeurs, on sépare ces valeurs par des virgules ou on donne un intervalle. Syntaxe pour une suite de valeurs : Selon expr Faire ... Cas v1,v2,...,vn : séquence_x ... FinSelon si l'une des valeurs v1, v2, …, vn est égale à la valeur de expr alors séquence_x est exécutée. Syntaxe pour un intervalle de valeurs : Selon expr Faire ... Cas xi..xf : séquence_x ... FinSelon si la valeur de expr est égale à l'une des valeurs entre xi et xf alors séquence_x est exécutée. Exemple 2.9 - le premier du mois : de 8h30 à 14h : L'accès à un musée est autorisé aux horaires suivants, selon la date du jour : - du 2 au 15 du mois : de 8h30 à 12h - du 17 au 25 du mois : l'entrée est autorisée un jour sur deux de 14h à 16h. Ecrire un algorithme qui demande la date du jour et qui affiche l'horaire correspondant si l'accès est autorisé, sinon il affiche "Accès non autorisé". Algorithme : acces_musee Var jour : Entier Début Ecrire("Entrer la date du jour : ") Lire(jour) Selon jour Faire Cas 1 : Ecrire("de 8h30 à 14h") Cas 2..15 : Ecrire("8h30 à 12h") Cas 17,19,21,23,25 : Ecrire("de 14h à 16h") Autrement : Ecrire("Accès non autorisé") Finselon
  21. 21. 18 Fin. Exemple 2.10 Les structures itératives : Ecrire un algorithme qui lit un caractère est affiche la nature du caractère : Lettre, Chiffre, Ponctuation (. : , ; ! ?). Si le caractère n'est pas connu, l'algorithme affiche "Caractère inconnu" Algorithme : type_caractere Var c : Caractère Début Ecrire("Entrer un caractere : ") Lire(c) Selon c Faire Cas 'a'..'z', 'A'..'Z' : Ecrire("Lettre") Cas '0'..'9' : Ecrire("Chiffre") Cas '.',':',',',';','!','?': Ecrire("Ponctuation") Autrement : Ecrire("Caractère inconnu") Finselon Fin. • Une structure itérative est une structure qui permet de répéter l'exécution d'une séquence d'instruction un certain nombre de fois. • Le nombre de répétition est déterminé par : - un test d'arrêt : instructions TantQue et Répéter. - un compteur : instruction Pour. 1. Instruction TantQue : • Permet de créer une structure itérative qui répète une séquence d'instructions tant qu'une condition est satisfaite : Syntaxe : TantQue (expr_condition) Faire séquence_x FinTantque où : expr_condition est une expression booléenne quelconques séquence_x est une suite d'instructions. Cette instruction test premièrement la valeur de expr_condition. Si cette dernière est VRAI alors elle exécute séquence_x, puis reteste expr_condition, si elle est encore VRAI, séquence_x est exécutée à nouveau, ainsi de suite jusqu'à ce que la valeur de expr_condition devienne FAUX. Exemple 2.11 : Ecrire un algorithme qui demande une note entre 0 et 20, jusqu'à ce que la note soit valide. Et à chaque fois que la valeur saisie est incorrecte, l'algorithme affichera le message "Note invalide".
  22. 22. 19 Algorithme : saisie_note_1 Var n : Entier Début Ecrire("Entrer une note entre 0 et 20 : ") Lire(n) TantQue ((n<0) OU (n>20)) Faire Ecrire("Note invalide") Lire(n) FinTantque Fin. Exemple 2.12 : Ecrire un algorithme qui permet de donner la somme de n premiers nombres entiers où n est un entier saisi en donnée. Algorithme : somme_n_1 Var n : Entier Var s : Entier /* la somme */ Var i : Entier /* prend les valeurs de 1 à n */ Début Ecrire("Entrer un entier : ") Lire(n) s ← 0 /* Initialisation */ i ← 1 /* Initialisation */ TantQue ( i ≤ n ) Faire s ← s+i i ← i+1 FinTantque Ecrire ("la somme est : ", s) Fin. Remarques  Si la condition d'arrêt est vraie et quelle n'est pas modifiée dans la séquence à répéter alors la boucle sera infinie (ne s'arrêtera jamais). :  Si la condition d'arrêt est fausse au début de l'exécution, la séquence dans la boucle ne sera jamais exécutée (le test est effectué avant l'exécution de la séquence). 2. Instruction Répéter • Comme TantQue, cette instruction utilise une condition d'arrêt, pour déterminer le nombre de répétition de la boucle, sauf que le test de cette condition est effectué à la fin de la boucle (après la première exécution de la séquence). Syntaxe : Répéter séquence_x Jusqu'à ce que (expr_condition) où : expr_condition est une expression booléenne quelconques séquence_x est une suite d'instructions. Cette instruction répète l'exécution de expr_condition , jusqu'à ce que expr_condition soit vraie.
  23. 23. 20 Exemple 2.13 • Notez que dans une boucle Répéter, la séquence d'instructions est exécutée au moins une fois. : Réécrire l'algorithme somme_n_1 (Exemple 2.12) en utilisant l'instruction Répéter. Algorithme : somme_n_1 Var n : Entier Var s : Entier /* la somme */ Var i : Entier /* prend les valeurs de 1 à n */ Début Ecrire("Entrer un entier : ") Lire(n) s ← 0 /* Initialisation */ i ← 1 /* Initialisation */ Répeter s ← s+i i ← i+1 Jusqu'à ce que ( i > n ) Ecrire ("la somme est : ", s) Fin. 3. Instruction Pour • Cette instruction crée une boucle en utilisant un compteur. Syntaxe - cmpt est une variable de type Entier (ou Caractère), qui doit être déclarée. : Pour compt ← val_init à val_fin séquence_x FinPour où : - val_init et val_fin sont des valeurs (variables ou des constantes) de même type que cmpt - séquence_x est une suite d'instructions. Cette instruction exécute séquence_x, pour cmpt prennant les valeurs : val_init, val_init+1, …,val_fin Exemple 2.14 : Réécrire l'algorithme qui calcule la somme des n premiers nombres entiers (Exemple2.12). Algorithme : somme_n_3 Var n : Entier Var s : Entier /* la somme */ Var i : Entier /* Compteur */ Début Ecrire("Entrer un entier : ") Lire(n) s ← 0 /* Initialisation */ Pour i ← 1 à n s ← s+i FinPour
  24. 24. 21 Ecrire ("la somme est : ", s) Fin. • La forme la plus complète de l'instruction Pour, utilise un pas, qui permet de contrôler les valeurs prises par le compteur entre la valeur initiale et la valeur finale. Syntaxe : Pour compt ← val_init à val_fin Pas val_pas séquence_x FinPour où : val_pas est une valeur de même type que cmpt. Cette instruction exécute séquence_x, pour toutes les valeurs de compt : val_init, val_init+pas, …,val_init+n*pas comprises entre val_init et val_fin. Exemple 2.15 • La forme de l'instruction Pour avec un pas peut toujours se ramener à la forme simple de l'instruction, moyennement un changement de variable. : Ecrire un algorithme qui affiche les n premiers entiers impaires dans l'ordre décroissant. Algorithme : multiples_1 Var n : Entier Var i : Entier /* Compteur */ Début Ecrire("Entrer un entier : ") Lire(n) Pour i ← n à 1 Pas (-1) Ecrire(2*i-1) aLaLigne FinPour Fin. Exemple 2.16 : Réécrire l'algorithme de l'exemple 2.15 avec la forme simple de la boucle Pour. Algorithme : multiples_2 Var n : Entier Var k : Entier /* Compteur */ Début Ecrire("Entrer un entier : ") Lire(n) Pour k ← 1 à n Ecrire(2*(n-k)+1) aLaLigne FinPour Fin.
  25. 25. 22 4. Choix de la boucle. • La boucle Pour peut toujours se traduire en une boucle TantQue (ou Répéter). Mais, dès qu'on connait le nombre d'itération, il devient plus naturel d'utiliser la boucle Pour. • Les boucles TantQue et Répéter utilisent toutes les deux une condition d'arrêt pour contrôler la boucle. Le passage de l'une à l'autre peut se faire moyennement un changement de la condition d'arrêt (et parfois dans l'ordre des instructions). • TantQue est la plus utilisée du fait que le contrôle se fait au début, mais la boucle Répéter peut s'avérer par fois utile, surtout si la valeur de la condition dépend de la première exécution de la séquence d'instructions de la boucle.
  26. 26. Tableaux
  27. 27. 24 Définition • Dans certains problèmes, on est amené à stocker et à gérer un ensemble de données éventuellement de même type afin de les traitées (Recherche, tri, …). L'utilisation des variables simples pour résoudre ce type de problème est fastidieuse, et inappropriée, voir impossible. Par exemple, pour manipuler 100 notes d'étudiants, il nous faut déclarer 100 variables. Or vu la structure de la mémoire d'un ordinateur, il s'avère qu'il est possible de stocker plusieurs valeurs de même type sur des blocs de mémoire contigus et de même taille, et connaissant l'adresse mémoire de du premier bloc, le nombre de blocs et leur taille commune, on peut accéder à tous les blocs moyennement un calcul simple. Les langages évolués ont utilisé cette technique de stockage et ont offert aux programmeurs la possibilité de manipuler plusieurs données de même type avec un seul identificateur. Ainsi, le programmeur déclare un identificateur avec un nombre de données et le type de ces données et le compilateur (le traducteur du langage) s'occupe de la réservation des blocs mémoire contigus et associe l'adresse du premier à l'identificateur déclaré. Et pour accéder à une de ces données, le programmeur mentionne tout simplement le rang (ou le numéro de cette donnée. Cette technique de structurer les données a donné naissance à ce qu'on appelle : Tableaux. • Un tableau est donc une structure de données qui permet de manipuler un ensemble de données de même type. • Pour déclarer un tableau en pseudo-code, on utilise la syntaxe suivante : Var nom_tableau[nombre_elements] : type_éléments Par exemple : Var notes[20] : Entier déclare un tableaux de 20 entiers. • Pour accéder à un élément du tableau, on utilise le nom du tableau suivi du numéro de l'élément entre crochets : notes[3] 10 n notes[5] + notes[2] • Le numéro de l'élément du tableau est dit indice (ou rang) de l'élément. • Le nombre d'éléments du tableau est dite taille (ou dimension) du tableau. • L'indice dans un tableau commence par 0 (convention utilisée par plusieurs langages évolués). Par exemple, les éléments du tableau notes, qui est de taille 20, sont : notes[0], notes[1], ..., notes[19]
  28. 28. 25 Algorithmes de Lecture/Ecriture • La plupart des algorithmes sur les tableaux, utilisent la boucle 'Pour' pour parcourir les tableaux, du fait que le nombre d'éléments est connu. • Les algorithmes de saisie et d'affichage des éléments d'un tableau sont standards. Exemple 3.1 Algorithmes de Recherche : Ecrire un algorithme qui lit et stocke N entiers, puis les affiche. Où N est un entier fixe (on prendra N = 20). Algorithme : acces_tableau Const N = 20 Var t[N]: Entier Var i : Entier Début /* SAISIE */ Pour i ← 0 à N-1 Ecrire("t[", i, "] = ") Lire(t[i]) FinPour /* AFFICHAGE */ Pour i ← 0 à N-1 Ecrire("t[", i, "] = ", t[i]) FinPour Fin Le fait d'utiliser la constante N permet d'avoir un corps d'algorithme indépendant du nombre d'éléments du tableau (il suffit de changer la valeur de la constante N, pour un tableau de taille différente de celle utilisée dans l'exemple). • L'un des problèmes classiques de recherche dans un tableau, consiste à chercher si un élément appartient au tableau ou si le tableau contient un élément qui vérifie une certaine propriété. Pour ce genre de problème, il suffit de parcourir le tableau jusqu'à ce qu'on trouve l'élément cherché. • La recherche doit s'arrêter une fois l'élément est trouvé ou tous les éléments sont consultés et aucun élément ne correspond. Par ailleurs, on doit utiliser la boucle TantQue (ou la boucle Répéter), puisque si on trouve l'élément en question, il sera inutile des consulter les autres éléments restants. Exemple 3.2 : Ecrire un algorithme qui permet de tester si un tableau d'entiers contient un multiple de 3. Algorithme : recherche_Mult3_1 Const N = 20 Var t[N]: Entier Var i : Entier Var trouve : Booléen
  29. 29. 26 Début ... /* Saisie ou initialisation du tableau t */ ... /* RECHERCHE */ i ← 0 Répéter trouve ← (t[i] % 3 = 0) i ← i + 1 Jusqu'à ce que (trouve OU (i ≥ N )) Si (trouve) Alors Ecrire("Elément trouvé au rang : ", i-1) Sinon Ecrire("Aucun élément n'est trouvé") Finsi Fin • Pour les tableaux triés, on peut améliorer l'efficacité des algorithmes de recherche en limitant la recherche à une certaine partie du tableau. L'algorithme dit Recherche par dichotomie pour les tableaux triés exploite le fait que les éléments, de tels tableaux, sont ordonnés. Il consiste à diviser le tableau en deux parties de tailles presqu'égales et en appliquant le test de recherche, on peut décider de la partie à consulter et de celle à éliminer. Puis, on recommence le procédé avec la partie conservée. Pour chercher, par exemple, une valeur 𝑥𝑥 dans le tableau trié [𝑎𝑎0, 𝑎𝑎1, ⋯ , 𝑎𝑎𝑛𝑛−1]  On pose 𝑚𝑚 = 𝑛𝑛/2 (division entière) et on compare 𝑥𝑥 avec 𝑎𝑎 𝑚𝑚  Si 𝑥𝑥 = 𝑎𝑎 𝑚𝑚 alors on a trouvé la solution et on arrête la recherche, sinon : - Si 𝑥𝑥 < 𝑎𝑎 𝑚𝑚 alors on doit donc chercher entre 0 et 𝑚𝑚 − 1 , on recommence alors le procédé pour chercher 𝑥𝑥 dans [𝑎𝑎0, 𝑎𝑎1, ⋯ , 𝑎𝑎 𝑚𝑚−1] - Sinon alors on recommence le procédé pour chercher 𝑥𝑥 dans [𝑎𝑎 𝑚𝑚+1, 𝑎𝑎1, ⋯ , 𝑎𝑎𝑛𝑛−1] Exemple : Recherche par dichotomie d'un entier dans un tableau trié. Algorithme : dichotomie Const N = 20 Var t[N]: Entier /* tableau trié d'entiers */ Var val : Entier /* Valeur à rechercher */ Var iDébut, iFin, iMilieu : Entier /* les indices */ Var trouvé : Booléen Début ... /* Saisie ou initialisation du tableau t */ /* le tableau t est supposé être trié */ /* Saisie ou initialisation de val : l'élément à chercher */ ... iDébut ← 0 iFin ← N-1 trouvé ← FAUX
  30. 30. 27 Répéter iMilieu ← (iDébut+iFin)/2 Si (t[iMilieu] = val) Alors trouvé = VRAI Sinon Si (val < t[iMilieu] val) Alors iFin ← iMilieu – 1 Sinon iDébut ← iMilieu + 1 FinSi FinSi Jusqu'à ce que (trouvé OU (iDébut > iFin)) Si (trouvé) Alors Ecrire(val, "se trouve au rang ", iMilieu) Sinon Ecrire("Aucun élément n'est trouvé") Finsi Fin • Un autre problème de recherche, consiste à trouver tous les éléments qui satisfont une condition donnée (comme par exemple le nombre d'occurrences d'un élément dans un tableau ou la recherche des extremums d'un tableau). Dans cette situation, la boucle Pour est donc la mieux adaptée, puisque on doit consulter tous les éléments du tableau. Exemple 3.3 : Ecrire un algorithme qui permet d'afficher et de compter les multiples de 3 d'un tableau d'entiers. Algorithme : recherche_Mult3_2 Const N = 20 Var t[N], i, nombre : Entier Début /* Saisie ou initialisation du tableau t */ ... /* RECHERCHE */ nombre ← 0 Pour i ← 0 à N-1 Si (t[i] % 3 = 0) Alors nombre ← nombre + 1 Ecrire(T[i]) Finsi FinPour Si (nombre ≠ 0) Alors Ecrire(nombre, " élément trouvés") Sinon Ecrire("Aucun élément n'est trouvé") Finsi Fin
  31. 31. 28 Exemple 3.4 Algorithmes de Tri : Ecrire un algorithme qui permet de trouver le minimum d'un tableau d'entiers. Algorithme : recherche_Mult3_2 Const N = 20 Var t[N], i : Entier Var minimum : Entier Début /* Saisie ou initialisation du tableau t */ ... /* RECHERCHE */ minimum ← t[0] Pour i ← 1 à N-1 Si (t[i] < minimum) Alors minimum ← t[i] Finsi FinPour Ecrire("Le minimum est : ", minimum) Fin • Le tri d'un tableau consiste à ordonner les éléments de ce tableau selon un ordre donné. L'ordre peut être croissant (du plus petit au plus grand) ou décroissant. • Il existe plusieurs algorithmes de tri plus ou moins efficaces. Nous étudierons, ici : - Tri par sélection. - Tri par insertion. - Tri à bulles. qui sont les moins efficaces, mais qui permettent de bien comprendre la notion de tri. 1. Tri par sélection • Ce tri consiste à chercher les éléments suivant leurs ordres et de les placer dans leurs endroits correspondants. Autrement dit, pour un tri croissant : - on cherche le premier (le plus petit) et on l'échange avec l'élément d'indice 0. - on cherche le deuxième et on l'échange avec l'élément d'indice 1. - etc…
  32. 32. 29 Exemple : Tri par sélection croissant d'un tableau d'entiers Algorithme de tri par sélection, dans l'ordre croissant, d'un tableau d'entiers : Algorithme : tri_selection Const N = 20 Var t[N] : Entier Var iMin, i, j : Entier Var temp : Entier /* pour l'échange */ Début /* Saisie ou initialisation du tableau t */ ... /* TRI SELECTION */ Pour i ← 0 à N-2 /* Recherche de l'indice du minimum */ iMin ← i Pour j ← i+1 à N-1 Si( t[j] < t[iMin] ) Alors iMin ← j Finsi FinPour /* Echange si le minimum n'est à sa place */ Si ( iMin ≠ i ) Alors temp ← t[i] t[i] ← t[iMin] t[iMin] ← temp Finsi Etape i = 4 : l'indice du minimum de [ti,..,t5] est 5, et i ≠ 5 ⇒ on échange les valeurs de ti et t5 t0 t1 t2 t3 t4 t5 1 2 3 4 8 6 t0 t1 t2 t3 t4 t5 1 2 3 4 6 8 Etape i = 3 : l'indice du minimum de [ti,..,t5] est 3, et i = 3 ⇒ Aucun changement t0 t1 t2 t3 t4 t5 1 2 3 4 8 6 Etape i = 2 : l'indice du minimum de [ti,..,t5] est 2, et i = 2 ⇒ Aucun changement t0 t1 t2 t3 t4 t5 1 2 3 4 8 6 Etape i = 1 : l'indice du minimum de [ti,..,t5] est 3, et i ≠ 3 ⇒ on échange les valeurs de ti et t3 t0 t1 t2 t3 t4 t5 1 4 3 2 8 6 t0 t1 t2 t3 t4 t5 1 2 3 4 8 6 Etape i = 0 : l'indice du minimum de [ti,..,t5] est 5, et i ≠ 5 ⇒ on échange les valeurs de ti et t5 t0 t1 t2 t3 t4 t5 6 4 3 2 8 1 t0 t1 t2 t3 t4 t5 1 4 3 2 8 6
  33. 33. 30 FinPour /* FIN DE TRI */ ... Fin 2. Tri par insertion Utilise le principe d'insertion d'un élément dans une liste triée. Il consiste à placer l'i-ème élément à sa bonne position dans la liste triée formée par les (i-1) premiers éléments. On procède comme suit : - on ordonne les deux premiers éléments, on obtient une liste triée de deux éléments. - on insère le troisième dans la liste triée formée par les deux premiers. - on insère le quatrième dans la liste triée formée les trois premiers. - etc. Exemple : Tri par insertion croissant du tableau [6,4,3,2,8,1]. Algorithme de tri par insertion, dans l'ordre croissant, pour un tableau d'entiers : Algorithme : tri_insertion Const N = 20 Var t[N] : Entier Var i, j : Entier Var x : Entier /* pour la sauvegarde */ Début /* Saisie ou initialisation du tableau t */ ... /* TRI INSERTION */ Pour i ← 1 à N-1 t0 t2 t3 t4 t5t1 t0 t2 t3 t4 t5t1 2 4 6 8 13 1 3 4 6 82Etape 5 : on insère, dans l'ordre, 1 dans la liste [2,3,4,6,8], ce qui donne [1,2,3,4,6,8] t0 t2 t3 t4 t5t1 t0 t2 t3 t4 t5t1 2 4 6 8 13 2 4 6 8 13Etape 4 : on insère, dans l'ordre, 8 dans la liste [2,3,4,6], ce qui donne [2,3,4,6,8] t0 t2 t3 t4 t5t1 t0 t2 t3 t4 t5t1 3 6 2 8 14 2 4 6 8 13Etape 3 : on insère, dans l'ordre, 2 dans [3,4,6], ce qui donne [2,3,4,6] t0 t2 t3 t4 t5t1 t0 t2 t3 t4 t5t1 4 3 2 8 16 3 6 2 8 14Etape 2 : on insère, dans l'ordre, 3 dans [4,6], on obtient [3,4,6] t0 t1 t2 t3 t4 t5 t0 t2 t3 t4 t5t1 6 4 3 2 8 1 4 3 2 8 16Etape 1 : on insère, dans l'ordre, 4 dans la liste [6], ce qui donne [4,6]
  34. 34. 31 x ← t[i] j ← i TantQue ((j > 0) ET (t[j-1] > x)) t[j] ← t[j-1] j ← j – 1 FinTantque t[j] ← x FinPour /* FIN DE TRI */ ... Fin 3. Tri à bulles Consiste à ordonner deux éléments consécutifs. On parcourt le tableau en comparant deux éléments consécutifs, s'ils ne sont pas ordonnés, on les échange. Si à la fin du parcours, on n'a effectué aucun échange, alors le tableau est trié, sinon on reparcourt le tableau en répétant la même opération. Exemple : Tri à bulles d'un tableau d'entiers [6,4,3,2,8,1] Etape 1 : 𝑃𝑃𝑃𝑃𝑃𝑃𝑃𝑃 𝑖𝑖 𝑎𝑎𝑎𝑎𝑎𝑎𝑎𝑎𝑎𝑎𝑎𝑎 𝑑𝑑𝑑𝑑 0 à 4, 𝑆𝑆𝑆𝑆 𝑡𝑡𝑖𝑖 > 𝑡𝑡𝑖𝑖+1 ⟹ é𝑐𝑐ℎ𝑎𝑎𝑎𝑎𝑎𝑎𝑎𝑎𝑎𝑎 𝑙𝑙𝑙𝑙𝑙𝑙 𝑣𝑣𝑣𝑣𝑣𝑣𝑣𝑣𝑣𝑣𝑣𝑣𝑣𝑣 𝑑𝑑𝑑𝑑 𝑡𝑡𝑖𝑖 𝑒𝑒𝑒𝑒 𝑡𝑡𝑖𝑖+1 Fin de l'étape 1 : 𝐼𝐼𝐼𝐼 𝑦𝑦 𝑎𝑎𝑎𝑎𝑎𝑎𝑎𝑎𝑎𝑎 é𝑐𝑐ℎ𝑎𝑎𝑎𝑎𝑎𝑎𝑎𝑎 𝑑𝑑𝑑𝑑𝑑𝑑𝑑𝑑 𝑐𝑐𝑐𝑐𝑐𝑐𝑐𝑐𝑐𝑐 é𝑡𝑡𝑡𝑡𝑡𝑡𝑡𝑡, 𝑑𝑑𝑑𝑑𝑑𝑑𝑑𝑑 𝑜𝑜𝑜𝑜 𝑟𝑟𝑟𝑟𝑟𝑟𝑟𝑟𝑟𝑟𝑟𝑟𝑟𝑟𝑟𝑟𝑟𝑟𝑟𝑟 𝑙𝑙𝑙𝑙 𝑝𝑝𝑝𝑝𝑝𝑝𝑝𝑝é𝑑𝑑é. On remarque qu'à la fin de l'étape 1, le maximum se trouve en dernière position, par suite lors de l'étape suivante, le parcours s'arrêtera à l'avant dernière. échange = VRAI t0 t1 t2 t3 t4 t5 6 4 3 2 8 1 t0 t1 t2 t3 t4 t5 4 6 3 2 1 8i = 4 i = 3 t0 t1 t2 t3 t4 t5 4 3 2 6 8 1 Aucune modification i = 2 t0 t1 t2 t3 t4 t5 4 3 6 2 8 1 t0 t1 t2 t3 t4 t5 4 3 2 6 8 1 échange ← VRAI échange ← VRAI t0 t1 t2 t3 t4 t5 4 6 3 2 8 1 t0 t1 t2 t3 t4 t5 4 3 6 2 8 1i = 1 échange ← VRAI t0 t1 t2 t3 t4 t5 6 4 3 2 8 1 t0 t1 t2 t3 t4 t5 4 6 3 2 8 1i = 0
  35. 35. 32 Algorithme de tri à bulles, dans l'ordre croissant, pour un tableau d'entiers Chaines de caractères et Tableaux : Algorithme : tri_bulles Const N = 20 Var t[N] : Entier Var i, k : Entier Var échange : Booléen /* pour contrôler l'échange */ Var temp : Entier /* pour l'échange */ Début /* Saisie ou initialisation du tableau t */ ... /* TRI A BULLES */ k ← N-1 Répéter /* début étape */ échange ← FAUX Pour i ← 0 à k-1 Si (t[i] > t[i+1]) Alors /* Echanger */ temp ← t[i] t[i] ← t[i+1] t[i+1] ← temp échange ← VRAI FinSi FinPour /* Fin étape */ k ← k-1 Jusqu'à ce que (NON(échange) OU (k ≤ 0)) /* FIN DE TRI */ ... Fin • Les langages évolués traitent les chaines de caractères comme des tableaux du fait que les caractères d'une chaine sont stockés les uns après les autres dans la mémoire. • Certains langages, Comme le C, ajoutent le caractère de code ASCII 0 ('0') à la fin des chaines de caractères pour marquer la fin d'une chaine, ce qui permet entre autres de connaitre sa longueur. • En algorithmique nous traiterons les chaines de caractères comme des tableaux de caractères qui se termine par le caractère '0'. Rappel : Code ASCII (voir Annexe) ASCII est une norme de codage des caractères en informatique, où chaque caractère est représenté par un entier. Certains langages permettent l'utilisation de ce code pour représenter un caractère. Cette représentation peut être sous forme d'une fonction qui pour un caractère donné donne le code ou inversement, soit sous forme d'écriture avec un caractère spécial.
  36. 36. 33 En langage C, par exemple en utilise la notation 'n' pour représenter le caractère de code n. Par exemple, le code du caractère a est 97, par suite 'a' et '97' représentent tous les deux le caractère a. En algorithmique, nous utiliserons, la représentation des caractères comme en C. Exemple de représentation d'une chaine de caractères : Si : Var ch : Chaine ... ch ← "Bonjour" Alors, ch est un tableau de caractères de longueur 8 et ch[7] est le caractère de code 0 (ch[7]='0'). Exemple 3.5 : Ecrire un algorithme qui lit une chaine de caractères et affiche sa longueur. Algorithme : longueur_chaine Var ch : Chaine Var longueur, i : Entier Début Ecrire("Entrer un chaine de caractères :") Lire(ch) i ← 0 TantQue(ch[i] ≠ '0') i ← i+1 FinTanque Ecrire("la chaine ", ch , " contient ", i, " caractères"). Fin. Exercice : Ecrire un algorithme qui lit une chaine de caractères et un caractère et retourne le nombre d'occurrences de ce dernier dans la chaine. 0 1 2 3 4 5 6 7 'B' 'o' 'n' 'j' 'o' 'u' 'r' '0' 66 111 112 106 111 117 114 0
  37. 37. 34 Tableaux à deux dimensions • Les éléments d'un tableau peuvent être de n'importe quel type. Lorsque les éléments d'un tableau sont aussi des tableaux, on aura alors un tableau de tableaux, ce qu'on appelle un tableau à deux dimensions ou une matrice. • Déclaration d'une matrice en pseudo-code : Var nom_tableau[dimension_1][dimension_2] : type_éléments Permet de déclarer - une matrice de dimension_1 lignes et dimension_2 colonnes ou - un tableau de taille dimension_1 dont les éléments sont des tableaux de taille dimension_2. Exemple • Pour accéder à un élément d'une matrice, il suffit de préciser l'indice de ligne et l'indice de colonne entre crochets. : Var m[4][5] : Entier /* une matrice 4 lignes et 5 colonnes */ /* m[i] est un tableau de taille 5 */ Exemple : m[0][3] ← 25 /* affecte 25 à l'élément qui se trouve dans dans la 1 ère ligne et la 4 ème colonne */ Exemple 3.6 : Ecrire un algorithme qui lit une matrice de 4 lignes et 5 colonnes et qui l'affiche. Algorithme : matrice Const Nl = 4 Const Nc = 5 Var m[Nl][Nc] : Réel Var iligne, icolonne : Entier Début /* Lecture d'une matrice */ Ecrire("Entrer une matrice ligne par ligne :") Pour iligne ← 0 à Nl-1 Pour icolonne ← 0 à Nc-1 Lire(m[iligne][icolonne]) FinPour FinPour /* Affichage d'une matrice */ Pour iligne ← 0 à Nl-1 Pour icolonne ← 0 à Nc-1 Ecrire(m[iligne][icolonne]) FinPour aLaLigne FinPour
  38. 38. 35 Fin. Exemple 3.6 • Signalement, enfin, qu'on peut déclarer et utiliser des tableaux multidimensionnels, de la même manière qu'un tableau à deux dimensions. : Ecrire un algorithme qui permet de trouver la somme de deux matrices carrés d'ordre N. Algorithme : matrice Const N = 4 Var m1[N][N], m2[N][N], m[N][N] : Réel Var i, j : Entier Début /* Lecture ou initialisation des matrices m1 et m2 */ ... /* Calcul de la somme m = m1+m2 */ Pour i ← 0 à N-1 Pour j ← 0 à N-1 m[i][j] = m1[i][j] + m2[i][j] FinPour FinPour ... Fin. Exemple - chaque m[i] est une matrice 5x3 : Var m[4][5][3] : Entier déclare un tableau à 3 dimensions. on le considère comme ((m[4])[5])[3], autrement dit : - chaque m[i][j] est un tableau de taille 3 - les m[i][j][k] sont des entiers
  39. 39. Fonctions et Procédures
  40. 40. 37 Principe • Lors de la réalisation des programmes, on relève les points suivants : - La maintenance d'un programme long (correction, modification, extension, mise au point), contenant un nombre assez important d'instructions, est fastidieuse. - Les mêmes séquences d'instructions, réalisant la même action ou faisant le même calcul, qui se répètent. Soit elles sont utilisées plusieurs fois dans un même algorithme, soit elles se répètent dans différents algorithmes. Par exemple, on utilise toujours la même séquence d'instructions pour calculer le maximum de deux nombres, et on retrouve cette séquence dans tous les algorithmes qui nécessitent le calcul du maximum et parfois on la retrouve plusieurs fois dans le même algorithme. On peut aussi citer plusieurs autres exemples, comme le calcul des fonctions mathématiques, statistiques, de recherche, de tri, … • Ceci nous amène à se poser les questions suivantes : - Peut-on décomposer un programme ? - Peut-on regrouper sous un même nom une séquence d'instructions qui réalisent une action commune ou qui effectuent le même calcul ? • La réponse est donnée au niveau de la machine. En effet, lors de l'exécution d'une suite d'instructions situées dans la mémoire, le langage machine (langage de base) permet le branchement (ou le saut) vers une autre zone mémoire qui contient d'autres instructions, de les exécuter et de retourner vers la séquence initiale pour terminer son exécution. Les langages évolués ont développé cette possibilité en offrant aux développeurs d'utiliser un nom pour symboliser et regrouper les séquences d'instructions qui seront traitées de cette manière (exécution après branchement et retour). Ainsi, le regroupement d'un ensemble d'instructions sous le même nom nous permet de : - Décomposer un algorithme - Réutiliser des séquences d'instructions sans avoir à les réécrire. - Structurer un programme d'une manière efficace pour faciliter sa maintenance et sa lisibilité • Cette manière d'organiser les algorithmes est dite programmation modulaire : elle est donc basée sur le fait qu'un programme est formé par plusieurs programmes dits modules : - Un programme principal : ou algorithme principal qui représente le point d'entrée (le début) du programme. - Des sous-programmes : où chaque sous-programme est une suite d'instructions indépendantes désignée par un nom et réalisant une action bien déterminée.
  41. 41. 38 • On distingue deux types de sous-programmes : - les fonctions : qui effectuent un calcul et retournent un résultat - les procédures : qui réalisent une action (affichage, recherche, tri, …) • Les sous-programmes sont paramétrables (définis avec des paramètres) ce qui assure leurs réutilisabilités et leurs efficacités. • Notons que la plus part des langages évolués ne font la différence entre procédure et fonction. Les fonctions 1. Définition Une fonction est donc un module paramétré qui réalise une action ou fait un calcul et retourne une valeur. • L'algorithme d'une fonction comporte : - En-tête : qui mentionne le nom de la fonction, les paramètres et leurs types et le type de la valeur qui sera retournée par la fonction. - Partie déclaration : qui déclare les variables propres à la fonction - Corps de la fonction : ensemble d'instructions entre les mots clés Début et Fin (comme tout autre algorithme) qui contient au moins une instruction Retourner, suivi d'une valeur. Cette instruction permet de quitter la fonction et de retourner à l'origine de l'appel. Syntaxe d'une fonction en algorithmique : Fonction nom_fonction(param1:type1, param2:type2,…) : type_retour /* partie déclaration */ Début ensemble_d'instructions contenant l'instruction Retourner val Fin val est un expression dont la valeur est de type type_retour. param1 de type1, param2 de type2,… sont des variables de la fonction qui devront être initialisées lors de l'appel de la fonction. Exemple 4.1 : Ecrire une fonction qui permet de retourner le minimum de deux nombres. Fonction min(a, b: Réel):Réel Var m : Réel Début Si( a ≤ b) Alors m ← a Sinon m ← b
  42. 42. 39 FinSi Retourner m Fin 2. Appel d'une fonction • Lorsqu'un programme appelle une fonction, le système sauvegarde l'état du programme appelant : ses variables, le point d'appel,…. Il crée ensuite un environnement propre à la fonction dans une zone mémoire, où elle sera exécutée avec ses propres données (variables, constantes, …), indépendamment du programme appelant. • Pour appeler (ou utiliser) une fonction on mentionne son nom avec les valeurs nécessaires pour qu'elle puisse initialiser ses paramètres. Exemple 4.2 1. initialiser les variables a et b de la fonction (qui sont les paramètres de la fonction) par les valeurs 3.5 et 2.6 (comme si on avait a ← 3.5 et b ← 2.6). : Un algorithme test de la fonction min : Algorithme test_min_1 Var z : Réel Début z ← min(3.5,2.6) Ecrire(z) Fin. Ici, on appelle la fonction min avec deux valeurs 3.5 et 2.6. Cet appel consiste à réaliser les actions suivantes dans l'ordre : 2. exécuter les instructions de la fonction (calculer m) 3. retourner la valeur de m. 4. au retour, remplacer min(3.5,2.6) par la valeur retournée. • D'une manière générale, l'appel d'une fonction peut se faire avec des expressions (variables, constantes, expressions composées). Dans ce cas, l'expression est évaluée avant l'appel de la fonction et la fonction sera appelée avec la valeur de l'expression. Exemple 4.3 : Algorithme test_min_2 Var x, y, z : Réel Début Ecrire("Entrer 3 réels") Lire(x) Lire(y) Lire(z) Ecrire(min(x-y,z)) Fin. Ici, la fonction min est appelée avec x-y et z. Autrement dit, dans min(x-y, z), x-y et z seront remplacés par leurs valeurs respectives avant l'appel.
  43. 43. 40 • L'appel de la fonction doit être avec le même nombre de valeurs que de paramètres et que chaque valeur doit être de même type que le paramètre correspondant. Exemple 4.4 • Une fonction peut ne pas avoir de paramètres. : On considère la fonction pair qui permet de tester si un nombre est pair, définie comme suit : Fonction pair(n : Entier):Booléen Début Retourner (n % 2 = 0) Fin Cette fonction retourne VRAI si elle est appelée avec une valeur entière paire, sinon elle retourne FAUX. pair(5) /* vaut FAUX */ pair(0.2) /* Erreur : 0.2 n'est pas un entier */ pair(2, 4) /* Erreur : trop de paramètres */ Exemple 4.5 • L'instruction Retourner n'est pas forcément la dernière instruction écrite dans le code et le code d'une fonction peut contenir plusieurs instructions Retourner, l'essentiel c'est lors de l'exécution de la fonction, si une instruction Retourner est rencontrée, alors l'exécution de la fonction est arrêtée et la valeur est retournée. : Fonction lit_entier():Entier Var n : Entier Début Ecrire("Entrer un entier : ") Lire(n) Retourner (n) Fin Cette fonction affiche un message, lit un entier et retourne la valeur lue. Pour appeler une telle fonction, il suffit de mentionner son nom avec des parenthèses vides Algorithme : test_lecture Var x : Entier Début ... x ← lit_entier() ... Fin Exemple 4.6 : Une autre version de la fonction min : Fonction min(a, b: Réel):Réel Début
  44. 44. 41 Si( a ≤ b) Alors Retourner(a) FinSi Retourner b Fin Si la condition (a ≤ b) est vraie, alors on exécute l'instruction Retourner(a), donc on quitte la fonction avec la valeur de a comme valeur de retour. Si la condition est fausse, on exécute Retourner(b) donc on retourne la valeur de b. • Une fonction peut appeler une ou plusieurs autres fonctions. Exemple 4.7 Les procédures : Ecrire une fonction qui calcule le minimum de trois réels. Fonction min3(a, b, c: Réel):Réel Début Retourner min(a,min(b,c)) Fin Dans cette exemple, on appelle premièrement la fonction min avec les valeurs de b et c, puis on appelle à nouveau la fonction min avec a et la valeur retournée par min(b,c). • Une procédure est une fonction qui ne retourne aucune valeur. Elle est essentiellement utilisée pour regrouper une séquence d'instructions, ce qui permet une bonne structuration du programme. Syntaxe d'une procédure en algorithmique : Procédure nom_procedure(param1:type1, param2:type2,…) /* partie déclaration */ Début ensemble_d'instructions Fin Exemple 4.8 : Ecrire une procédure qui permet d'afficher le maximum et le minimum de trois nombres. On définit premièrement la fonction max : Fonction max(a, b: Réel):Réel Début Si( a ≥ b) Alors Retourner(a) Sinon Retourner b FinSi Fin
  45. 45. 42 Puis la procédure minmax3 : Procédure minmax3(a, b, c: Réel) Var min_3, max_3 : Réel Début min_3 ← min(min(a,b), c) max_3 ← max(max(a,b), c) Ecrire("Le minimum de ", a, b, c, " est ", min_3) Ecrire("Le maximum de ", a, b, c, " est ", max_3) Fin • Notons qu'on peut utiliser dans une procédure l'instruction Retourner, sans mentionner aucune valeur, pour quitter la procédure. Transmission des paramètres Premièrement, notons qu'il y a une différence entre les identificateurs utilisés lors de la définition d'une fonction et ceux utilisés lors de l'appel de la fonction : - Les identificateurs utilisés dans la définition d'une fonction sont dits paramètres formels ou tout simplement paramètres. Ils représentent des variables de la fonction et y sont utilisés ainsi (une fonction peut changer leurs valeurs) - Les expressions (constantes, variables, …) utilisés lors de l'appel de la fonction, sont dites des paramètres effectifs ou arguments. La fonction n'utilise que leurs valeurs pour initialiser ses paramètres. Exemple 4.9 : On considère la fonction suivante : Fonction raz(a:Entier) : Entier Début Ecrire("Au début, le parametre a = ", a) a ← 0 Ecrire("A la fin, le parametre a = ", a) Retourner a Fin Cette fonction affiche la valeur initiale de son paramètre, change sa valeur, et la retourne. La valeur retournée par cette fonction est toujours 0. Nous utilisons cette fonction dans l'algorithme test suivant : Algorithme : test_raz Var a, b : Entier Début a ← 2 b ← raz(a) Ecrire("La variable b = ', b)
  46. 46. 43 Ecrire("La variable a = ', a) Fin Dans b ← raz(a), on remplace premièrement a par sa valeur, donc cette instruction est équivalente à b ← raz(2). On appelle donc la fonction raz avec l'argument 2. En plus la valeur de a restera 2, puisque cette variable n'a subi aucune modification. L'exécution de cet algorithme donne : Au début le parametre a = 2 A la fin, le parametre a = 0 La variable b = 0 La variable a = 2 • Nous avons défini, ici, avec le même nom a un paramètre de la fonction et une variable de l'algorithme appelant. Même s'ils ont le même nom, ils représentent deux entités différentes, l'une est propre à la fonction (c'est le paramètre) et l'autre est une variable de l'algorithme que la fonction ne connait pas. • D'autre part, la fonction ne change pas la valeur de l'argument, puisque si l'argument est une variable ou une expression alors cette dernière sera remplacée par sa valeur avant l'appel. Exemple 4.10 : Citons un autre exemple classique de la fonction qui échange les valeurs de deux variables. Procédure echange(a,b:Entier) Var temp Début temp ← a a ← b b ← temp Fin Cette procédure n'aura aucun effet si elle est appelée dans un algorithme Algorithme : test_echange Var x, y : Entier Début x ← 2 y ← 5 echange(x,y) Ecrire("x = ', x) Ecrire("y = ', y) Fin Ici, l'appel echange(x,y) est équivalent à echange(2,5). Par ailleurs, dans la procédure les paramètres a et b seront initialisés respectivement par 2 et 5, puis on échange leurs valeurs. Les variables x et y de test_echange ne subissent aucune modification.
  47. 47. 44 • En résume, lors de l'appel d'une fonction, cette dernière reçoit la valeur de son argument. Autrement dit, une fonction n'utilise que les valeurs de ses arguments. On parle alors d'une transmission d'arguments par valeur. • Il s'avère que dans certaines situations, on a besoin des fonctions qui modifient les valeurs des arguments (comme par exemple la fonction raz ou la fonction échange). Pour ce, on doit transmettre à la fonction l'adresse de la variable (ou sa référence). Les langages évolués offrent cette possibilité et permettent la transmission d'arguments par adresse ou par référence. • En algorithmique, pour préciser qu'un argument sera transmis par adresse (ou par référence) on ajoute le mot clé Var : Par exemple : Fonction nom_fonction(Var x:type1, ...) : type_retour précise que le paramètre x recevra la même adresse (ou une référence) de l'argument lors de l'appel. Ainsi la fonction echange devra être : Procédure echange(Var a,b:Entier) Var temp Début temp ← a a ← b b ← temp Fin Dans ce cas, avec le programme test_echange : Algorithme : test_echange Var x, y : Entier Début x ← 2 y ← 5 echange(x,y) Ecrire("x = ', x) Ecrire("y = ', y) Fin lors de l'appel de echange(x,y), le paramètre a (resp b) sera un représentant de la variable x (resp y). Autrement dit, tout changement de a affectera x.
  48. 48. 45 Fonctions sur les tableaux • Les fonctions et les procédures peuvent avoir des paramètres de type tableaux, pour ce on peut : - Soit définir un paramètre de la fonction comme un tableau de taille fixe, comme par exemple Procédure nom_fonction(tab[20]:Entier,...):type_retour - Soit définir un paramètre de la fonction comme un tableau sans mentionner sa dimension, par exemple : Procédure nom_fonction(tab[]:Entier,...):type_retour Mais dans ce cas, il faut nécessairement informer la fonction de la taille du tableau, en ajoutant un autre paramètre Procédure nom_fonction(tab[]:Entier, taille:Entier,...) :type_retour Il est clair que la deuxième forme est plus générale que la première. Exemple 4.11 • D'autre part, vu la manière comment on définit le tableau, à savoir que le nom du tableau représente l'adresse du premier élément du tableau, alors si une fonction à un paramètre de type tableau, elle peut accéder aux éléments de ce dernier et donc elle peut changer leurs valeurs. : Ecrire une procédure qui permet d'affiche les éléments d'un tableau d'entiers Procédure affiche_tab(t[]:Entier, taille:Entier) Var i : Entier Début Pour i ← 0 à taille-1 Ecrire(t[i]) FinPour Fin Exemple 4.12 • Ainsi on peut convertir tous les algorithmes sur les tableaux mentionnés précédemment en procédure ou fonction. : Ecrire une fonction qui permet de saisir un tableau d'entiers : Procédure lecture_tab(t[]:Entier, taille:Entier) Var i : Entier Début Pour i ← 0 à taille-1 Lire(t[i]) FinPour Fin.
  49. 49. 46 Récursivité • Une fonction peut appeler n'importe quelle autre fonction ou procédure, comme elle peut s'appeler elle-même, dans ce cas on dit que la fonction est récursive. Exemple 4.13 : La fonction qui permet de calculer le factoriel d'un entier d'une manière récursive : On sait que : 0! = 1 𝑛𝑛! = 𝑛𝑛 × (𝑛𝑛 − 1)! si 𝑛𝑛 ≥ 1 Ce qui donne Fonction factoriel( n : Entier ) : Entier Var fact : Entier Début Si (n = 0) Alors fact ← 1 Sinon fact = n * factoriel(n-1) FinSi Retourner fact Fin. Exemple 4.14 • Pour les fonctions récursives, il faut toujours s'assurer qu'elle possède un point de sortie (ou un cas limite) sinon la fonction créera une boucle infinie. : La suite de Fibonacci est définie par : 𝑢𝑢0 = 1 𝑢𝑢1 = 1 𝑢𝑢𝑛𝑛 = 𝑢𝑢𝑛𝑛−1 + 𝑢𝑢𝑛𝑛−2 Pour 𝑛𝑛 ≥ 2 La fonction récursive qui permet de trouver le terme d'ordre n est donnée par : Fonction fibonacci( n : Entier ) : Entier Début Si ((n = 0) OU (n=1)) Alors Retourner 1 FinSi Retourner fubonacci(n-1) + fubonacci(n-2) Fin.
  50. 50. Exercices
  51. 51. 48 Série 1 Exercice 1.1: Donner les valeurs des variables a, b et c, après l'exécution de l'algorithme suivant. Algorithme : exercice_01 Var a,b:Entier Début a ← 5 b ← a + 4 c ← a + b b ← a + b a ← c Fin. Exercice 1.2 1. Ecrire un algorithme qui permet d'échanger les valeurs de deux variables saisies. : 2. Ecrire un algorithme qui permet de permuter les valeurs de 3 variables saisies. Exercice 1.3 : Ecrire un algorithme qui lit le prix hors taxe unitaire d'un produit et le nombre d’articles et qui calcule le prix total hors taxe et le prix TTC, sachant que le taux de TVA est fixé à 20%. L'algorithme doit afficher tous les détails des données, à savoir le prix unitaire, la quantité, … Exercice 1.4 : Ecrire un algorithme qui lit un nombre entier de trois chiffres et affiche les chiffres d'unités, de dizaines et de centaines. Exercice 1.5 1. Ecrire un programme qui lit un nombre de secondes et qu'il convertit et l'affiche sous la forme : heures: minutes: sec. : 2. Ecrire un algorithme qui donne la durée d'un trajet connaissant l'heure de départ et l'heure d'arrivée. Les horaires sont supposés être du même jour. 3. Ecrire un algorithme qui donne l'heure d'arrivée connaissant l'heure de départ et la durée du trajet. On suppose que la durée ne dépasse pas 24 heures.
  52. 52. 49 Série 2 Exercice 2.1 Ecrire un algorithme qui lit 3 nombres et informe l'utilisateur si ces nombres sont ordonnés dans l'ordre croissant ou non. Ecrire un algorithme qui permet de résoudre l'équation : 𝑎𝑎 𝑥𝑥2 + 𝑏𝑏 𝑥𝑥 + 𝑐𝑐 = 0. Exercice 2.2 où 𝑎𝑎, 𝑏𝑏 et 𝑐𝑐 sont des réels données. Ecrire un algorithme qui permet de retrouver la partie entière d'un réel. Rappelons que la partie entière d'un nombre 𝑥𝑥 est un entier 𝑛𝑛 tel que : 𝑛𝑛 < 𝑥𝑥 < 𝑛𝑛 + 1 Exercice 2.3 Ecrire un algorithme qui permet de calculer la puissance 𝑛𝑛𝑘𝑘 où 𝑛𝑛 et 𝑘𝑘 sont deux entiers donnés, sans utiliser l'opérateur prédéfini. Exercice 2.4 Donner un algorithme qui permet de calculer le terme 𝑢𝑢𝑁𝑁 où 𝑁𝑁 est un entier donné. Exercice 2.5 On considère la suite (Fibonacci) 𝑢𝑢0 = 1, 𝑢𝑢1 = 1, 𝑢𝑢𝑛𝑛+2 = 𝑢𝑢𝑛𝑛+1 + 𝑢𝑢𝑛𝑛 Ecrire un algorithme qui permet de calculer la somme et le produit des 𝑁𝑁premiers nombres impairs. Exercice 2.6 Ecrire un algorithme qui lit une note 𝑁𝑁 entre 0 et 20 et affiche la mention correspondante. Exercice 2.7 𝑁𝑁 < 10 Ajourné 10 ≤ 𝑁𝑁 < 12 Passable 12 ≤ 𝑁𝑁 < 14 Assez Bien 14 ≤ 𝑁𝑁 < 16 Bien 16 < 𝑁𝑁 Très Bien L'algorithme doit contrôler la validité de la note. Exercice 2.8 Ecrire un algorithme qui lit N notes où N est un entier donnée, contrôle la saisie de ces notes et affiche, la moyenne, la plus grande note et la plus petite note.
  53. 53. 50 Série 3 Exercice 3.1 Ecrire un algorithme qui lit un tableau d'entiers et qui affiche les entiers pairs suivi des entiers impairs de ce tableau, et qui donne à la fin le nombre de chacun des deux groupes. Exercice 3.2 Ecrire un algorithme qui permet de saisir un nombre fixe de valeurs et qui les range dans l'ordre croissant au fur et à mesure. Exercice 3.3 Dans le déroulement des algorithmes de tri (par sélection, par insertion et à bulles), donner tous les différents états du tableau suivant : ⌈6, 15, 3, 21, 9, 12, 14, 8⌉ Exercice 3.4 Ecrire l'algorithme de tri à bulles dans l'ordre décroissant pour un tableau d'entiers. Exercice 3.5 Ecrire un algorithme qui permet d'inverser un tableau. Exercice 3.6 Ecrire un algorithme qui permet de fusionner deux tableaux triés de taille respectivement N et M (où N et M sont deux entiers fixes) Exercice 3.7 Ecrire un algorithme qui lit une chaine de caractères et qui donne le nombre d'espaces blancs contenu dans cette chaine. Exercice 3.8 Ecrire un algorithme qui permet de calculer le produit de 2 matrices carrées.
  54. 54. 51 Série 4 Exercice 4.1 Ecrire une procédure qui prend arguments un entier n et un caractère c et affiche n fois le caractère c. Utiliser cette procédure pour écrire un algorithme qui lit un entier N et qui affiche un triangle de hauteur N comme dans l'exemple suivant où la hauteur est 4 : * *** ***** ******* Exercice 4.2 Ecrire une fonction qui permet de tester si un nombre est premier ou non. Exercice 4.3 Ecrire une fonction qui donne le nombre d'occurrences d'un caractère dans une chaine de caractères. En déduire une fonction qui donne le nombre de voyelles contenues dans une chaine de caractères. Exercice 4.4 Ecrire une procédure qui permet d'inverser une chaine de caractères. Exercice 4.5 Ecrire une fonction qui permet convertir une chaine de caractères en un entier, de la manière suivante : Si la chaine ne contient que des chiffres alors la chaine renvoie l'entier représenté par ces chiffres (par exemple pour "153", la fonction retourne l'entier 153). Et si la chaine contient un caractère autre qu'un chiffre alors la fonction retourne 0. Exercice 4.7 Ecrire une version itérative et une version récursive d'une fonction qui permet de calculer le pgcd de deux entiers strictement positifs, sachant que : Si a et b sont deux entiers strictement positifs, alors : 𝑝𝑝𝑝𝑝𝑝𝑝𝑝𝑝(𝑎𝑎, 𝑏𝑏) = 𝑎𝑎 si 𝑎𝑎 = 𝑏𝑏 𝑝𝑝𝑝𝑝𝑝𝑝𝑝𝑝(𝑎𝑎, 𝑏𝑏) = 𝑝𝑝𝑝𝑝𝑝𝑝𝑝𝑝(𝑎𝑎, 𝑏𝑏 − 𝑎𝑎) si 𝑎𝑎 < 𝑏𝑏 𝑝𝑝𝑝𝑝𝑝𝑝𝑝𝑝(𝑎𝑎, 𝑏𝑏) = 𝑝𝑝𝑝𝑝𝑝𝑝𝑝𝑝(𝑎𝑎 − 𝑏𝑏, 𝑏𝑏) si 𝑎𝑎 > 𝑏𝑏
  55. 55. 52 Série 5 Exercice 5.1 Ecrire une fonction qui permet de calculer à 10−8 prés la racine carrée d'un nombre strictement positif par la méthode de dichotomie. : Principe de la méthode dichotomie Etant donné une fonction 𝑓𝑓 strictement croissante sur l'intervalle [𝑎𝑎, 𝑏𝑏]. On suppose que l'équation 𝑓𝑓(𝑥𝑥) = 0 admet une solution dans cet intervalle. : Pour trouver une valeur approchée à ε prés de l'unique solution de 𝑓𝑓(𝑥𝑥) = 0 dans [𝑎𝑎, 𝑏𝑏] : On pose : 𝑎𝑎0 = 𝑎𝑎 et 𝑏𝑏0 = 𝑏𝑏 . Si (𝑎𝑎0 + 𝑏𝑏0)/2 n'est pas la solution alors si 𝑓𝑓 � 𝑎𝑎0 + 𝑏𝑏0 2 � > 0, on pose 𝑎𝑎1 = 𝑎𝑎0 et 𝑏𝑏1 = 𝑎𝑎0 + 𝑏𝑏0 2 sinon, on pose 𝑎𝑎1 = 𝑎𝑎0 + 𝑏𝑏0 2 et 𝑏𝑏1 = 𝑏𝑏0 La solution est donc entre 𝑎𝑎1et 𝑏𝑏1 On répète ce procédé d'encadrement de la solution jusqu'à ce qu'on trouve 𝑎𝑎𝑛𝑛 et 𝑏𝑏𝑛𝑛 tels que 𝑏𝑏𝑛𝑛 − 𝑎𝑎𝑛𝑛 < 𝜀𝜀 Ainsi, 𝑎𝑎𝑛𝑛 (ou 𝑏𝑏𝑛𝑛) sera la valeur approchée de la solution à ε prés. Exercice 5.2 Ecrire une fonction qui prend en paramètres un tableau représentant un polynôme et un réel 𝑥𝑥 et qui calcule la valeur de ce polynôme en 𝑥𝑥 de la manière suivante : 𝑃𝑃(𝑥𝑥) = 𝑎𝑎0 + (𝑎𝑎1 + (… (𝑎𝑎𝑛𝑛−1 + 𝑎𝑎𝑛𝑛 𝑥𝑥)𝑥𝑥)𝑥𝑥)𝑥𝑥 : On représente un polynôme par le tableau de ses coefficients. Ainsi : 𝑃𝑃 = 𝑎𝑎0 + 𝑎𝑎1 𝑋𝑋 + ⋯ + 𝑎𝑎𝑛𝑛 𝑋𝑋𝑛𝑛 est représenté par le tableau [𝑎𝑎0, 𝑎𝑎1, … , 𝑎𝑎𝑛𝑛 ] Exercice 5.3 1. Ecrire une fonction qui permet de saisir une note entre 0 et 20 avec contrôle (l'utilisateur devra répéter la saisie jusqu'à ce que la note soit valide). : On se propose d'étudier les notes de N étudiants dans M modules différents (N et M sont des constantes données). Pour ce, on numérote les étudiants de 0 à N-1 et les modules de 0 à M-1 et on utilise un tableau, à deux dimensions, note[N][M] où : note[i][k] représente la note de l'étudiant i dans le module k. 2. Ecrire une fonction qui permet de calculer la moyenne des nombres d'un tableau passé en paramètre. 3. Ecrire deux fonctions qui permettent de retrouver le minimum et le maximum d'un tableau passé en paramètre. 4. Ecrire une fonction qui permet d'afficher les éléments d'un tableau passé en paramètre. 5. Ecrire une fonction qui permet d'afficher la mention correspondante à une note donnée (voir exercice 2.7).
  56. 56. 53 6. Ecrire un algorithme, utilisant ces fonctions, qui après avoir saisi les notes des étudiants par module, affiche tous les résultats : - Pour chaque étudiant, il affiche son numéro, ses notes, sa moyenne et sa mention. - Pour chaque module, il affiche la moyenne des notes, la plus grande et la plus petite note obtenues dans le module. - Pour la promotion, il affiche la moyenne générale, la plus grande et la plus petite moyenne obtenues. Exercice 5.4 : Ecrire une fonction qui permet de tester si les éléments d'un tableau d'entier sont tous différents. Une grille de Sudoku est une matrice 9x9 dont les éléments sont tous entre 1 et 9. Une telle grille est valide si tous les chiffres de la même ligne, où de la même colonne, où des sous-grilles (3x3), sont tous différents Ecrire une fonction qui permet de tester si une grille de Sudoku est valide.
  57. 57. 54 Solution 5.1 La racine carrée de 𝑥𝑥 est la solution positive de l'équation 𝑡𝑡2 = 𝑥𝑥 . : On pose alors 𝑓𝑓(𝑡𝑡) = 𝑡𝑡2 − 𝑥𝑥. Pour 𝑥𝑥 = 1 ou 𝑥𝑥 = 0 , la solution est 𝑥𝑥. Pour 𝑥𝑥 > 1, on a 1 < √𝑥𝑥 < 𝑥𝑥 , on cherche la solution donc dans [1, 𝑥𝑥]. Pour 𝑥𝑥 < 1, on a 𝑥𝑥 < √𝑥𝑥 < 1 , on cherche la solution donc dans [𝑥𝑥, 1]. Fonction sqrt(x:Réel): Réel Const eps = 1.0 e(-8) Var a,b,c : Réel Début Si((x=0) OU (x=1)) Alors Retourner x FinSi Si ( x < 1) Alors a ← x b ← 1 Sinon a ← 1 b ← x FinSi TantQue (b-a) > eps Faire c ← (a+b)/2 Si(c*c – x = 0) Alors Retourner c Sinon Si (c*c – x > 0) Alors b ← c Sinon a ← c FinSi FinSi FinTantQue Retourner a Fin Solution 5.2 : Fonction polynome(a[] : Réel, degre:Entier, x:Réel): Réel Var i: Entier Var val : Réel Début val ← a[degre] Pour i ← degre-1 à 0 pas -1 val ← a[i]+ val*x FinPour Retourner val Fin
  58. 58. 55 Solution 5.3 : /* Lecture d'une note entre 0 et 20 */ Fonction Lire_note() : Réel Var x : Réel Début Répeter Lire(x) Jusqu'à ce que (0 ≤ x) ET (x ≤ 20) Retourner x Fin /* fonction de calcul de la moyenne */ Fonction moyenne(t[]: Réel, n : Entier): Réel Var total : Réel Début total ← 0 Pour k ← 0 à n-1 total ← total + note[i][k] FinPour Retourner total/n Fin /* Fonction qui calcule le minimum d'un tableau */ Fonction min(t[]: Réel, n : Entier): Réel Var i : Entier Var m : Réel Début m ← t[0] Pour i ← 1 à n-1 Si (t[i] < m) Alors m ← t[i] FinSi FinPour Retourner m Fin /* Fonction qui calcule le maximum d'un tableau */ Fonction max(t[]: Réel, n : Entier): Réel Var i : Entier Var m : Réel Début m ← t[0] Pour i ← 1 à n-1 Si (t[i] > m) Alors m ← t[i] FinSi FinPour Retourner m Fin
  59. 59. 56 /* Procédure qui affiche les éléments d'un tableau */ Procédure Affiche(t[] : Réel, n : Entier) Var k : Entier Début Pour k ← 0 à n-1 Ecrire(t[k]) FinPour Fin /* Procédure qui affiche la mention */ Procédure Affiche_mention(moyenne : Réel) Début Si (moyenne < 10) Ecrire("Ajourné") Retourner FinSi Si (moyenne < 12) Ecrire("Passable") Retourner FinSi Si (moyenne < 14) Ecrire("Assez Bien") Retourner FinSi Si (moyenne < 16) Ecrire("Bien") Retourner FinSi Si (moyenne < 10) Ecrire("Très Bien") Retourner FinSi Fin /* Programme principale de gestion des notes */ Algorithme : gestion_notes Var note[N][M] : Réel /* tableau des notes */ Var moy[N] : Réel /* tableau des moyennes */ Var temp[N] : Réel Var i, k : Entier Début /* Saisie des notes par modules */ Pour k ← 0 à M-1 Ecrire ("Entrer les notes du module ", k) Pour i ← 0 à N-1 Ecrire("Note étudiant ", i , " :") note[i][k] ← Lire_note() FinPour FinPour
  60. 60. 57 /* calcule de la moyenne des étudiants */ Pour i ← 0 à N-1 moy[i] ← moyenne(note[i],M) FinPour /* Afficahge des résultats */ Pour i ← 0 à N-1 Ecrire("Etudiant ", i) Affiche(note[i], M) Ecrire(moy[i]) Affiche_mention(moy[i]) FinPour /* Résultats par module */ Pour k ← 0 à M-1 Ecrire("Résultats module : ", k) Pour i ← 0 à N-1 temp[i] ← note[i][k] FinPour Ecrire("Moyenne : ", moyenne(temp, N)) Ecrire("Plus petite note ;", min(temp, N)) Ecrire("Plus grande note ;", max(temp, N)) FinPour /* Résultats de la promotion */ Ecrire("Résultats de la promotion : ") Ecrire("Moyenne Générale : ", moyenne(moy, N)) Ecrire("Plus petite moyenne ;", min(moy, N)) Ecrire("Plus grande moyenne ;", max(moy, N)) Fin Solution 5.4 : Fonction qui permet de tester si tous les éléments d'un tableau d'entiers sont différents. Fonction tous_diff(t[]:Entier, n:Entier): Booléen Var k : Entier Début Pour i ← 0 à n-2 Pour j ← i+1 à n-1 Si (t[j] = t[i]) Retourner FAUX FinSi FinPour FinPour Retourner VRAI Fin
  61. 61. 58 Fonction qui permet de vérifier une grille de sudoku 9x9. Fonction verifier_grille(t[9][9] : Entier): Booléen Const N = 9 Var temp[N] : Entier Var i,j,k,l : Entier Début /* Verifie si tous les éléments sont entre 1 et 9 */ Pour i ← 0 à N-1 Pour j ← 0 à N-1 Si((t[i][j] < 1) OU (t[i][j] > 9)) Alors Retourner FAUX FinSi FinPour FinPour /* Vérification des lignes */ Pour i ← 0 à N-1 Si( NON tous_diff(t[i], N)) Alors Retourner FAUX FinSi FinPour /* Vérification des colonnes */ Pour j ← 0 à N-1 /* On extrait la colonne dans le tableau temp */ Pour i ← 0 à N-1 temp[i] ← t[i][j] FinPour /* on vérifie le tableau */ Si( NON tous_diff(temp, N)) Alors Retourner FAUX FinSi FinPour /* Vérification des sous-grilles */ /* On repere les sous grilles par un couple (l,k) où l est la ligne et k est la colonne avec k et l entre 0 et 2 Ainsi la grille (l,k) est formée par les 3 lignes 3l, 3l+1 et 3l+2 et les colonnes 3k, 3k+1 et 3k+2 On place les éléments de la sous-grille dans le tableau temporaire temp dans l'ordre suivant : (3l,3k), (3l,3k+1), (3l,3k+2), …, (3l+2,3k+2) Donc, l'élément d'indice i de temp recevra l'élément (3l+q, 3k+r) où q et r sont le quotient et le reste de la division euclidienne de i par 3 */ Pour l ← 0 à 2 Pour k ← 0 à 2 Pour i ← 0 à N-1 temp[i] ← grille[3*l+(i/3)][3*k+(i%3)] FinPour Si( NON tous_diff(temp, N)) Alors
  62. 62. 59 Retourner FAUX FinSi FinPour FinPour /* Si après les différentes vérifications on n'a pas quitté la procédure alors la grille est valide */ Retourner VRAI Fin
  63. 63. Annexe
  64. 64. 61 Table ASCII Code Caractère Code Caractère Code Caractère 32 espace 64 @ 96 ` 33 ! 65 A 97 a 34 " 66 B 98 b 35 # 67 C 99 c 36 $ 68 D 100 d 37 % 69 E 101 e 38 & 70 F 102 f 39 ' 71 G 103 g 40 ( 72 H 104 h 41 ) 73 I 105 i 42 * 74 J 106 j 43 + 75 K 107 k 44 , 76 L 108 l 45 - 77 M 109 m 46 . 78 N 110 n 47 / 79 O 111 o 48 0 80 P 112 p 49 1 81 Q 113 q 50 2 82 R 114 r 51 3 83 S 115 s 52 4 84 T 116 t 53 5 85 U 117 u 54 6 86 V 118 v 55 7 87 w 119 w 56 8 88 X 120 x 57 9 89 Y 121 y 58 : 90 Z 122 z 59 ; 91 [ 123 { 60 < 92 124 | 61 = 93 ] 125 } 62 > 94 ^ 126 ~ 63 ? 95 _ 127 Suppr

×