← Retour au cours
▶ Aperçu gratuit · Leçon offerte

Leçon 2 — Programmation, algorithmique et structures de données

⏱ 90 min · 🎬 Lecon · 🏆 15 XP
🎬
Vidéo en production
Notre équipe pédagogique tourne actuellement cette leçon avec un·e formateur·rice expert·e. Le contenu textuel ci-dessous est complet et utilisable dès maintenant.

Leçon 2 — Programmation, algorithmique et structures de données

Python, Java, PHP, JavaScript : syntaxe, complexité asymptotique, POO, patrons de conception et programmation dynamique.

🎯 Objectifs SMART de la leçon

  • Écrire et lire du code Python, Java, PHP et JavaScript à un niveau intermédiaire (CRUD complet, classes, exceptions) en autonomie.
  • Calculer en moins de 2 minutes la complexité asymptotique O(f(n)) d'une fonction de moins de 30 lignes.
  • Choisir la structure de données optimale (liste, pile, file, dictionnaire, arbre, tas, graphe) selon le scénario métier.
  • Appliquer les 4 piliers de la POO et 5 patrons GoF (Singleton, Factory, Observer, Strategy, MVC) sur un mini-projet.
  • Transformer une fonction récursive O(2n) en algorithme O(n) avec mémoïsation, et le démontrer.

0. Prérequis

Avoir validé la Leçon 1 (référentiel et parcours). Connaître les opérateurs de base d'un langage impératif (Python ou JavaScript). Avoir installé sur sa machine : Python 3.11+, OpenJDK 17+, PHP 8.2+, Node.js 20+, un IDE (VS Code, IntelliJ IDEA Community ou PyCharm Educational). Lecture conseillée : docs.python.org/3/tutorial.

1. Introduction contextuelle — programmer, ce n'est pas que coder

En 1968, lors de la célèbre conférence de l'OTAN à Garmisch, le terme « crise du logiciel » est forgé : les projets explosent en coût, en délai et en bugs. C'est l'acte de naissance du génie logiciel et de l'algorithmique scientifique. Depuis, Donald Knuth (TAOCP, 1968-2025), Edsger Dijkstra (« Go To Statement Considered Harmful », 1968), Niklaus Wirth (Pascal) et plus récemment Guido van Rossum (Python, 1991) ont forgé les fondations.

Au BUT Informatique, la R1.01 Initiation au développement au S1 forme à la rigueur algorithmique (séquence, sélection, itération, fonctions, complexité). La R2.01 Développement orienté objets au S2 introduit Java et les 4 piliers de la POO. Les SAÉ S1.01 (« Implémentation d'un besoin client »), S2.01 (« Développement d'une application »), S3.01 (« Développement d'une application complexe ») cadrent l'évaluation.

L'enjeu : un développeur senior produit 10 à 20 lignes de code par jour en moyenne — ce qui semble peu jusqu'à comprendre que 80 % du temps est consacré à lire du code, débuguer, tester et documenter. La lisibilité prime donc sur le « code malin ». Le programme du BUT cible donc autant la maîtrise syntaxique que les bonnes pratiques : nommage, modularité, tests unitaires, revues de code.

Cette leçon couvre les langages obligatoires, la théorie de la complexité, les structures de données, la POO, les patrons et la programmation dynamique. Tous les exemples sont fonctionnels et testés.

2. Les langages enseignés en BUT Informatique

Le Programme National BUT Informatique 2021 impose un tronc multilingue. Aucun parcours ne se limite à un seul langage.

LangageParadigme principalUsage métierSemestre d'apparitionCréateur / date
PythonMulti-paradigme (impératif + objet)Scripting, IA, data science, prototypageS1Guido van Rossum, 1991
JavaOrienté objet purBackend entreprise, Android, JEES2James Gosling (Sun), 1995
JavaScript / TypeScriptMulti-paradigme (fonctionnel + objet)Frontend (React, Vue), Node.jsS2Brendan Eich, 1995 / Microsoft, 2012
SQLDéclaratif (ensembliste)Requêtage bases relationnellesS1Boyce & Chamberlin (IBM), 1974
PHPMulti-paradigmeWeb côté serveur (Symfony, Laravel)S3Rasmus Lerdorf, 1995
C / C++Impératif / ObjetSystèmes, embarqué, performanceS3 (selon parcours)Kernighan & Ritchie 1972 / Stroustrup 1985
Bash / PowerShellShell scriptingAdministration, automatisationS2 (ASRV)Bourne 1979 / Microsoft 2006
Selon Bjarne Stroustrup, créateur du C++ : « Il n'existe que deux types de langages : ceux dont les gens se plaignent et ceux que personne n'utilise. » — Choisir un langage, c'est accepter ses compromis.
Source : stroustrup.com.

3. Notions fondamentales d'algorithmique

3.1 Structures de contrôle universelles

Tout algorithme repose sur 3 structures de base, démontrées formellement par Corrado Böhm & Giuseppe Jacopini en 1966 (« Flow Diagrams, Turing Machines and Languages with Only Two Formation Rules », Communications of the ACM) :

  1. Séquence : les instructions s'exécutent l'une après l'autre.
  2. Sélection (alternative) : if / else if / else, ou switch / match.
  3. Itération (répétition) : while, for, do-while.

Toute fonction calculable peut être écrite avec ces 3 structures — c'est l'équivalence de Turing. Le goto est donc strictement évitable (cf. Dijkstra, 1968).

3.2 Complexité asymptotique — notation O

La notation O (Big-O) mesure le comportement d'un algorithme quand n → +∞, indépendamment du matériel.

NotationTypen=10n=1 000n=10⁶ExempleVerdict
O(1)Constant111Accès tableau par index, lookup HashMapIdéal
O(log n)Logarithmique31020Recherche dichotomique, arbre équilibréExcellent
O(n)Linéaire101 00010⁶Parcours liste, max d'un tableauTrès bon
O(n log n)Quasi-linéaire3310 0002×10⁷Tri fusion, tri rapide moyen, FFTBon (limite tri optimal)
O(n²)Quadratique10010⁶10¹²Tri bulle, tri insertion, comparaison naïveAcceptable jusqu'à 10 000
O(n³)Cubique1 00010⁹10¹⁸Multiplication matricielle naïve, Floyd-WarshallLent au-delà de 500
O(2ⁿ)Exponentiel1 02410³⁰⁰Fibonacci naïf, sous-ensembles, sac à dos exactInutilisable au-delà de 40
O(n!)Factoriel3,6 MVoyageur de commerce force brute, permutationsInutilisable au-delà de 12
Selon Donald Knuth (« Structured Programming with go to Statements », Computing Surveys, 1974) : « Premature optimization is the root of all evil. » — La lisibilité prime sur l'optimisation tant que la complexité asymptotique reste correcte.
Source : doi.org/10.1145/356635.356640.

4. Structures de données classiques

4.1 Structures linéaires

StructureAccèsInsertionSuppressionRechercheUsage typique
Tableau dynamique (list, ArrayList)O(1)O(1) fin / O(n) milieuO(n)O(n)Collection ordonnée générique
Liste chaînée simpleO(n)O(1) si pointeurO(1) si pointeurO(n)File d'attente, historique navigateur
Liste doublement chaînéeO(n)O(1)O(1)O(n)LRU cache, undo/redo
Pile (Stack, LIFO)O(1) sommetO(1) pushO(1) popO(n)Parcours profondeur, undo, parser
File (Queue, FIFO)O(1)O(1) enqueueO(1) dequeueO(n)Parcours largeur, tâches asynchrones
Table de hachage (dict, HashMap)O(1) moyenO(1) moyenO(1) moyenO(1) moyenIndex, cache, dictionnaire

4.2 Structures hiérarchiques

  • Arbre binaire de recherche (BST) — recherche/insertion O(log n) si équilibré, O(n) dégénéré.
  • Arbre AVL / Rouge-Noir — auto-équilibré, garantit O(log n).
  • Tas (heap) — extraction min/max en O(log n), usage : files de priorité (Dijkstra), tri par tas.
  • Trie (arbre de préfixes) — autocomplétion, correcteur orthographique, dictionnaires.
  • B-tree / B+ tree — index bases de données (PostgreSQL, MySQL InnoDB).

4.3 Graphes

  • Représentation : matrice d'adjacence O(V²) en espace, ou liste d'adjacence O(V+E).
  • Parcours : DFS (Depth-First Search, pile) — trouve cycles, composantes connexes. BFS (Breadth-First Search, file) — plus court chemin en nombre d'arêtes.
  • Plus court chemin pondéré : Dijkstra (1959, poids positifs, O((V+E) log V)), Bellman-Ford (poids négatifs, O(V·E)), Floyd-Warshall (tous-vers-tous, O(V³)).
  • Arbre couvrant minimum (MST) : Kruskal (tri arêtes + union-find), Prim (tas).

4.4 Schéma ASCII — pile vs file

PILE (LIFO)             FILE (FIFO)
                        +---+---+---+---+
[Pop] <- sommet  -> [D] | A | B | C | D | -> [Dequeue C? Non, A]
                        +---+---+---+---+
[Push E] ->        [E]    debut             fin
[D] [C] [B] [A]    base    Enqueue --> (cote fin)

5. Application pratique — 4 cas concrets résolus

✏️ Cas pratique n°1 — Recherche dichotomique en Python (O(log n))

Sur un tableau trié de 1 million d'éléments, la recherche dichotomique trouve l'élément en max 20 comparaisons (log₂ 10⁶ ≈ 20), contre 500 000 en moyenne pour une recherche linéaire.

# Recherche dichotomique en Python - O(log n) en temps, O(1) en espace
def dicho(tab, x):
    g, d = 0, len(tab) - 1
    while g <= d:
        m = (g + d) // 2
        if tab[m] == x:
            return m
        elif tab[m] < x:
            g = m + 1
        else:
            d = m - 1
    return -1

# Test
print(dicho([1, 3, 5, 7, 9, 11, 13], 7))   # 3
print(dicho([1, 3, 5, 7, 9, 11, 13], 4))   # -1

Complexité : O(log n). Préconditions impératives : tableau trié en ordre croissant et accès indexé O(1) (liste Python OK).

✏️ Cas pratique n°2 — Même algo en Java (typage statique)

// Recherche dichotomique en Java 17 - O(log n)
public class Dicho {
    public static int rechercher(int[] tab, int x) {
        int g = 0, d = tab.length - 1;
        while (g <= d) {
            int m = g + (d - g) / 2; // evite overflow int
            if (tab[m] == x) return m;
            if (tab[m] < x) g = m + 1;
            else d = m - 1;
        }
        return -1;
    }
    public static void main(String[] args) {
        int[] t = {1, 3, 5, 7, 9, 11, 13};
        System.out.println(rechercher(t, 7));  // 3
    }
}

Détail crucial : m = g + (d - g) / 2 évite l'overflow d'entier qui frappait java.util.Arrays.binarySearch avant Java 6 (cf. Joshua Bloch, Google Research, 2006).

✏️ Cas pratique n°3 — Fibonacci : naïf vs mémoïsé (POO + récursivité)

# Fibonacci naif - O(2^n) - inutilisable au-dela de n=35
def fib_naif(n):
    if n < 2:
        return n
    return fib_naif(n - 1) + fib_naif(n - 2)

# Fibonacci memoise - O(n) en temps, O(n) en espace
from functools import lru_cache

@lru_cache(maxsize=None)
def fib(n):
    if n < 2:
        return n
    return fib(n - 1) + fib(n - 2)

# Iteratif - O(n) en temps, O(1) en espace (optimal)
def fib_iter(n):
    a, b = 0, 1
    for _ in range(n):
        a, b = b, a + b
    return a

print(fib_iter(100))  # 354224848179261915075

Comparaison de temps réel pour n=35 : fib_naif ≈ 4 s, fib mémoïsé < 1 ms, fib_iter < 1 µs. Voir functools.lru_cache dans la documentation Python officielle.

✏️ Cas pratique n°4 — Pattern Observer en PHP 8 (POO)

<?php
// Pattern Observer (GoF, 1994) - PHP 8 avec types stricts
declare(strict_types=1);

interface Observer {
    public function notifier(string $event): void;
}

class Sujet {
    /** @var Observer[] */
    private array $observers = [];

    public function attacher(Observer $o): void {
        $this->observers[] = $o;
    }

    public function diffuser(string $event): void {
        foreach ($this->observers as $o) {
            $o->notifier($event);
        }
    }
}

class Logger implements Observer {
    public function notifier(string $event): void {
        echo "[LOG] " . $event . PHP_EOL;
    }
}

$sujet = new Sujet();
$sujet->attacher(new Logger());
$sujet->diffuser("Utilisateur connecte");
// [LOG] Utilisateur connecte

Le pattern Observer est l'un des 23 patrons GoF (Gamma, Helm, Johnson, Vlissides, 1994). PHP 8 introduit le typage strict (declare(strict_types=1);) qui rejette les conversions implicites string ↔ int.

6. Programmation orientée objet (POO) — 4 piliers

Les 4 piliers de la POO :

  1. Encapsulation — visibilité private / protected / public. Cacher les détails internes.
  2. Héritage — relation « est-un » (extends en Java, : en Python, extends en PHP). Réutiliser le comportement parent.
  3. Polymorphisme — méthodes redéfinies (override), surcharge (overload), méthodes virtuelles. Un même appel peut produire des comportements différents.
  4. Abstraction — classes abstract, interfaces. Exposer un contrat sans dévoiler l'implémentation.

Les 23 design patterns GoF (Gamma, Helm, Johnson, Vlissides, « Design Patterns », Addison-Wesley, 1994) sont étudiés en S4. Les 5 patrons incontournables BUT :

PatronFamille GoFProblème résoluExemple BUT Info
SingletonCréationUne seule instance globaleConnexion DB unique
Factory MethodCréationDéléguer la création d'objetsConstruire User/Admin/Guest
ObserverComportementNotifier 1-N abonnésEvent bus, MVC
StrategyComportementChoisir un algo à l'exécutionTri rapide vs fusion selon n
MVCArchitectural (Reenskaug 1979)Séparer données / vue / logiqueSymfony, Spring MVC, Laravel

7. Pièges fréquents et erreurs à éviter

⚠️ RecursionError Python (récursion non bornée)

En Python, la limite de récursion par défaut est 1 000 niveaux (cf. sys.getrecursionlimit()). Un Fibonacci récursif naïf au-dessus de fib(35) dépasse 4 s ; au-dessus de fib(990), RecursionError. Solutions :

  • Privilégier la version itérative.
  • Utiliser functools.lru_cache ou functools.cache (Python 3.9+) pour mémoïser.
  • En dernier recours : sys.setrecursionlimit(10000) — risque de stack overflow OS.

⚠️ GIL (Global Interpreter Lock) Python

Le GIL sérialise l'exécution des threads CPython, rendant le threading inefficace pour du CPU-bound. Solutions : multiprocessing, concurrent.futures.ProcessPoolExecutor, ou Python 3.13+ avec mode no-GIL expérimental (PEP 703).

⚠️ Anti-pattern N+1 (vu en BD)

Lister 1 000 utilisateurs puis pour chacun faire un SELECT de leurs commandes = 1 001 requêtes au lieu d'une seule jointure ou d'un IN (...). Frappe massivement les ORM (Doctrine, Hibernate, SQLAlchemy). Détection : activer le query log Doctrine ou utiliser EXPLAIN ANALYZE.

⚠️ Mutables par défaut Python (gotcha)

# MAUVAIS : la liste par defaut est partagee entre TOUS les appels
def ajouter(elem, lst=[]):
    lst.append(elem)
    return lst

print(ajouter(1))  # [1]
print(ajouter(2))  # [1, 2]  <-- inattendu !

# BON
def ajouter(elem, lst=None):
    if lst is None:
        lst = []
    lst.append(elem)
    return lst

💡 Astuce dev — toujours documenter la complexité

En SAÉ, indiquez TOUJOURS la complexité au-dessus de votre fonction (commentaire). C'est un critère explicite de notation. Exemple :

# dicho(tab, x) -> O(log n) en temps, O(1) en espace.
# Precondition : tab trie en ordre croissant.
def dicho(tab, x): ...

Les revues de code en entreprise (GitHub PR, GitLab MR) suivent la checklist Google Engineering Practices : lisibilité, complexité, tests, sécurité, perf.

8. Mini-quiz prose intégré (3 QCM corrigés en fin de section)

  1. Question 1 : Quelle est la complexité asymptotique d'une recherche dichotomique dans un tableau trié de n éléments ?
    (a) O(1) — (b) O(log n) — (c) O(n) — (d) O(n²)
  2. Question 2 : Lequel de ces 4 piliers POO permet à une sous-classe de redéfinir une méthode de la classe parente ?
    (a) Encapsulation — (b) Héritage — (c) Polymorphisme — (d) Abstraction
  3. Question 3 : Quel pattern GoF garantit qu'une classe ne sera instanciée qu'une seule fois dans toute l'application ?
    (a) Factory — (b) Observer — (c) Strategy — (d) Singleton

Correctifs : 1=b (log₂ n comparaisons max) ; 2=c (polymorphisme = override) ; 3=d (Singleton, Gang of Four 1994).

9. Synthèse — 10 points-clés à retenir

  • 4 langages obligatoires : Python (S1), Java (S2), JavaScript (S2), SQL (S1). PHP/C selon parcours.
  • Böhm-Jacopini 1966 : toute fonction calculable = séquence + sélection + itération.
  • Complexité O : O(1) < O(log n) < O(n) < O(n log n) < O(n²) < O(n³) < O(2ⁿ) < O(n!).
  • Tri optimal comparatif : O(n log n) (borne de Shannon). Plus rapide impossible sans hypothèses.
  • Structures linéaires : tableau (O(1) accès), pile LIFO, file FIFO, hash map O(1) moyen.
  • Structures hiérarchiques : BST/AVL O(log n), tas (file priorité), trie (autocomplétion).
  • Graphes : DFS (pile), BFS (file), Dijkstra (plus court chemin), Kruskal/Prim (MST).
  • 4 piliers POO : encapsulation, héritage, polymorphisme, abstraction.
  • Gang of Four 1994 : 23 design patterns. Top 5 BUT : Singleton, Factory, Observer, Strategy, MVC.
  • Mémoïsation = recette anti-récursion explosive : Fibonacci passe de O(2ⁿ) à O(n).

10. Pour aller plus loin

Continuez le parcours 🚀

Inscrivez-vous pour accéder aux 5 autres leçons + le quiz final.

Créer mon compte
🍪 Nous utilisons des cookies essentiels et, avec ton accord, des cookies analytiques. En savoir plus

⚙️ Préférences cookies

Choisis quels cookies tu acceptes — modifiable à tout moment.

🔐 Essentiels (obligatoires)Authentification, session, sécurité. Toujours actifs.
📊 Analytics anonymesMesure d'audience anonymisée — aucune donnée personnelle.
📣 MarketingPublicités ITAG pertinentes sur d'autres sites.
💬 Contactez-nous sur WhatsApp