Académique Documents
Professionnel Documents
Culture Documents
BDR
Cours de
Programmation
Avancée en
Python
Base de
Données
Relationnelles
05 Septembre 2019
TS STIC 1
2018 - 2019
A Celui qui peut tout
1
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
2
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
Objectifs
▪ Gérer des données de bases structurées ou non
▪ Approfondir les connaissances en langage de programmation évolué et moderne
3
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
4
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
Savoir-faire :
▪ Comprendre et décrire les rôles des différents éléments d'une architecture trois
tiers
▪ Recourir aux concepts des bases de données relationnelles ;
▪ Traduire les questions posées dans un langage de requête en respectant sa syntaxe
▪ Prototyper et créer une base de données simple, à l’aide d’un outil interactif
▪ Consulter une base de données à travers des requêtes de type SQL ;
5
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
1.1. Principes
1.1.1. Définition
Il est difficile de donner une définition exacte de la notion de base de données. Une
définition très générale pourrait être :
Une Base de données est un ensemble organisé d'informations avec un objectif commun.
Peu importe le support utilisé pour rassembler et stocker les données (papier, fichiers,
etc.), dès lors que des données sont rassemblées et stockées d'une manière organisée dans
un but spécifique, on parle de base de données.
1.1.2. Enjeux
Les bases de données ont pris une place importante en informatique, et particulièrement
dans le domaine de la gestion. L'étude des bases de données a conduit au développement
de concepts, méthodes et algorithmes spécifiques, notamment pour gérer les données en
mémoire secondaire (i.e. disques durs). En effet, dès l'origine de la discipline, les
informaticiens ont observé que la taille de la RAM ne permettait pas de charger l'ensemble
d'une base de données en mémoire. Cette hypothèse est toujours vérifiée, car le volume
des données ne cesse de s'accroître sous la poussée des nouvelles technologies du WEB.
Ainsi, les bases de données de demain devront être capables de gérer plusieurs dizaines de
Téra-Octets de données, géographiquement distribuées à l'échelle d'Internet, par
plusieurs dizaines de milliers d'utilisateurs dans un contexte d'exploitation changeant (on
ne sait pas très bien maîtriser ou prédire les débits de communication entre sites) voire
sur des nœuds volatiles. En physique des hautes énergies, on prédit qu'une seule expérience
produira de l'ordre du pétaoctet de données par an.
Comme il est peu probable de disposer d'une technologie de disque permettant de stocker
sur un unique disque cette quantité d'informations, les bases de données se sont orientées
vers des architectures distribuées ce qui permet, par exemple, d'exécuter potentiellement
6
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
plusieurs instructions d'entrée/sortie en même temps sur des disques différents et donc
de diviser le temps total d'exécution par un ordre de grandeur.
En règle générale, une application peut aisément se diviser en trois niveaux distincts : les
données, le traitement de ces données et leur affichage.
La couche de donnée regroupe le stockage et les mécanismes d’accès des données de façon
qu’elle soit utilisable par l’application au niveau traitement.
La couche de traitement concerne à la fois les tâches à réaliser par l’application sur les
données et les traitements nécessaires pour donner suite à une action de l’utilisateur.
Enfin, la couche de présentation qui permet l’interaction entre l’utilisateur et l’application.
Ces trois niveaux pouvant être imbriqués ou repartis, leur découpage et leur répartition
permettent de distinguer les architectures applicatives suivantes :
– L’architecture un tiers,
– L’architecture deux tiers,
– L’architecture trois tiers.
Dans une architecture deux tiers ou client-serveur de données, le poste client se contente
de déléguer la gestion des données à un service spécialisé. Ce type d’application permet de
tirer parti de la puissance des ordinateurs déployés en réseau pour fournir à l'utilisateur
une interface riche, tout en garantissant la cohérence des données, qui restent gérées de
façon centralisée.
7
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
▪ Troisième niveau (Couche accès aux données) : Elle consiste en la partie gérant
l’accès aux données qui sont destinées à être conservées sur la durée, voire de
manière définitive.
Une base de données relationnelle est une base de données structurée suivant les principes
de l'algèbre relationnelle.
Le père des bases de données relationnelles est Edgar Frank Codd. Chercheur chez IBM à
la fin des années 1960, il étudiait alors de nouvelles méthodes pour gérer de grandes
quantités de données, car les modèles et les logiciels de l'époque ne le satisfaisaient pas.
Mathématicien de formation, il était persuadé qu'il pourrait utiliser des branches
spécifiques des mathématiques (la théorie des ensembles et la logique des prédicats du
premier ordre) pour résoudre des difficultés telles que la redondance des données,
l'intégrité des données ou l'indépendance de la structure de la base de données avec sa
mise en œuvre physique.
8
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
En 1970, il publia un article où il proposait de stocker des données hétérogènes dans des
tables, permettant d'établir des relations entre elles. De nos jours, ce modèle est
extrêmement répandu, mais en 1970, cette idée était considérée comme une curiosité
intellectuelle. On doutait que les tables puissent être jamais gérées de manière efficace
par un ordinateur.
Ce scepticisme n'a cependant pas empêché Codd de poursuivre ses recherches. Un premier
prototype de Système de gestion de bases de données relationnelles (SGBDR) a été
construit dans les laboratoires d'IBM. Depuis les années 80, cette technologie a mûri et a
été adoptée par l'industrie. En 1987, le langage SQL, qui étend l'algèbre relationnelle, a
été standardisé.
C'est dans ce type de modèle que se situe ce cours de base de données.
Le responsable de la bibliothèque des CPGE peut être tenté de gérer les emprunts par un
simple fichier sur un tableur, par exemple Excel. Les premières lignes de ce fichier peuvent
ressembler à ce qui suit :
On peut tout de suite relever les différentes difficultés avec cette organisation. Elles sont
les suivantes :
– l'orthographe des différents noms de famille peut manquer de cohérence;
– l'orthographe des différents titres des ouvrages peut manquer de cohérence : Mme ou
Madame Bovary ?
– la recopie des numéros de téléphone est fastidieuse et comporte des risques d'erreur ;
– même l'entrée de la date peut poser problème (les autres emprunts du même
emprunteur).
– personne différente portant le même nom
– mise à jour d’une donnée de l’emprunteur
– et si le fichier comportait des milliers de lignes !
9
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
La séparation d’objets reliés permet une avancée importante : Les modifications sont
maintenant plus simples à gérer.
Dans le modèle relationnel, les données sont organisées en tableaux à deux dimensions qui
s’appellent relations.
La table des Livres comporte une colonne identifiant le livre, puis une autre identifiant
l'auteur par son numéro, et de même pour le genre. Les titres ne sont pas répétés, ce qui
garantit la cohérence des données.
10
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
Les bases de données (BD) sont généralement gérées par un système appelle Système de
gestion de base de données relationnelles (SGBDR). C’est un système qui permet de gérer
une BD partagée par plusieurs utilisateurs simultanément
Le SGBD permet de :
Décrire les données indépendamment des applications (de manière intrinsèque) avec un
langage de définition des données DATA DEFINITION LANGUAGE (DDL)
Manipuler les données : interroger et mettre à jour les données sans préciser
d'algorithme d'accès. Dire QUOI sans dire COMMENT à l’aide d’un langage de requêtes
déclaratif.
Exemple : quels sont les noms des produits de prix inférieur à 100 F ?
On parle de langage de manipulation des données DATA MANIPULATION
LANGUAGE (DML)
Contrôler les données (intégrité) : vérification de contraintes d'intégrité
Exemple : personne dont le salaire compris entre 400F et 20000 F
1.4.1. Définition
Les requêtes SQL (Strutured Query Language) soumisent par l’utilisateur sont traduites
par le SGBD en opérations de l’algèbre relationnelle.
Utilisateur BD
SGBDR
L’algèbre relationnelle est un ensemble d’opérateurs qui prennent en entrée des relations
et qui produisent en sortie des relations.
Objectif : localiser des données dans la base qui répondent à un certain critère ou aux
besoins de l’utilisateur.
11
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
Les objets de base souvent référencés dans la modélisation relationnelle sont les domaines,
les relations, les attributs, les degrés et les tuples.
Domaine :
Le domaine représente un ensemble fini de valeur possible pour un attribut donné auquel
on définit aussi un ensemble d’opérateurs pouvant être appliqués aux valeurs du domaine.
Tuple
Grossièrement, un tuple est un enregistrement (une ligne) dans la base de données.
Plus formellement, un tuple est un élément atomique comportant un entête et un corps.
L'entête est un ensemble des noms d’attributs et de leurs domaines et le corps est un
ensemble de triplets <Nom du domaine, Nom d’attribut, Valeur>
Attribut :
Un attribut est simplement la valeur associée à un des triplets d’un tuple.
Clé candidate :
Une clé candidate est un ensemble des données (attribut) permettant d’indexer chaque
ligne d’une table donnée de manière différenciée. On utilise souvent une ou plusieurs clés
candidates comme clé primaire.
12
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
Relation
Une relation (ou table) est un élément constitué d’un entête et d’un corps. L’entête est un
ensemble des noms d’attributs et de leurs domaines et le corps est un ensemble de tuples
ayant le même entête que la relation.
Soient : R : une relation ; Att1, Att2, … , Attn : des attributs ; D1, D2, … , Dn : les domaines
des attributs respectifs.
13
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
Restriction (Sélection) σ
La sélection consiste à extraire d’une relation les occurrences (lignes) satisfaisant au(x)
critère(s) de sélection.
Formalisme : R2 = SELECTION (R1/ C(Att)) où C(Att) est le critère de sélection sur
le(s) attribut(s) Att.
Critères de sélection :
▪ Opérateurs de comparaison : <, <=, =, >, >=, ? (Entre un champ ou attribut et une
valeur)
▪ Opérateurs logiques : ET, OU (entre deux comparaison)
▪ NON (pour renverser la comparaison)
Projection Π
La projection d'une relation consiste en la mise en place d'une nouvelle relation en ne
retenant que certaines colonnes (attributs) et en supprimant les occurrences en double.
Formalisme : R2 = PROJECTION (R1/colonne 1, colonne 2, …)
R2 est la table résultat, R1 est la table utilisée par la projection. Pas de duplication des
occurrences.
14
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
Division /
La division permet de trouver les occurrences d’une table qui sont associées à toutes les
occurrences d’une autre table (qui le plus souvent est le résultat d’une sélection).
Formalisme : R = DIVISION (dividende, diviseur) ou R = dividende / diviseur
Attention au sens, chers Prépas !!!
DIVISION(PARTICIPER, EPREUVE)
Le nom des athlètes qui ont participé aux épreuves de 200 m et de 400 m et de 110 m H.
Jointure
La jointure consiste à créer une nouvelle table à partir de deux tables ayant un champ
commun (attribut) et vérifiant un critère de jointure.
Formalisme :
R3 = JOINTURE(R1, R2/R1.attr_jointure op_comparaison R2.attr_jointure)
Cours Notes
La jointure entre les deux tables Cours et Notes se fait à travers l’attribut Nom_cours
▪ JOINTURE(Cours, Notes/ Cours.nom_cours = Notes.nom_cours)
15
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
Les opérateurs ensemblistes sont les mêmes qu’en mathématiques, dans la théorie des
ensembles. Vous avez certainement vu ce cours en MPSI.
Union (U)
L’union de deux tables est l'ensemble des occurrences qui appartiennent soit à la première
table, soit à la deuxième, soit aux deux tables. C’est la traduction du OU logique.
Remarque : pas de duplication des n-uplets.
Formalisme : Soient R1 et R2 deux relations. On a : R = R1 U R2 ou R = UNION (R1 , R2)
Intersection (∩ )
L'intersection de deux relations est l'ensemble des occurrences qui sont présentes dans
les deux relations. C’est la traduction du ET logique.
Formalisme : R = R1 ∩ R2 ou R = INTERSECTION (R1, R2)
16
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
Différence –
La différence entre deux tables est l'ensemble des occurrences qui appartiennent à une
table sans appartenir à la seconde. Le but est d’obtenir l’ensemble des tuples d’une relation
qui ne figurent pas dans une autre. Attention, cette opération a un sens.
Formalisme : R = R1 - R2 ou R = DIFFERENCE (R1, R2). Opération non commutative.
S-R
Produit cartésien x
Le produit cartésien de deux tables consiste à combiner toutes les possibilités
d’associations d’occurrences des deux tables. Chaque ligne de R1 sera concaténée à chaque
ligne de R2.
Formalisme : R = R1 x R2 ou R = PRODUIT (R1, R2)
17
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
Convention : Les clés primaires sont soulignées et les clés étrangères sont précédées d’un
dièse (#).
Q1 : Donnez la liste des avions dont la capacité est supérieure à 350 passagers.
R1 = ……………………………………………………………………………………………………………………………………………………
Q3 : Quels sont les numéros des pilotes en service et les villes de départ de leurs vols ?
R3 = ……………………………………………………………………………………………………………………………………………………
Q5 : Quel est le nom des pilotes domiciliés à Paris dont le salaire est supérieur à 15000 F
?
18
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
R5.1 = ……………………………………………………………………………………………………………………………………………………
R5.2 = ……………………………………………………………………………………………………………………………………………………
R5 = ……………………………………………………………………………………………………………………………………………………
Q6 : Quels sont les avions (numéro et nom) localisés à Nice ou dont la capacité est
inférieure à 350 passagers ?
R6.1 = ……………………………………………………………………………………………………………………………………………………
R6.2 = ……………………………………………………………………………………………………………………………………………………
R6 = ……………………………………………………………………………………...………………………………………………………………
Q8 : Quels sont les numéros des pilotes qui ne sont pas en service ?
R8.1 = ……………………………………………………………………………………………………………………………………………………
R8.2 = ……………………………………………………………………………………………………………………………………………………
R8 = ………………..……………………………………………………………………………………………………………………………………
Q9 : Quels sont les vols (numéro, ville de départ) effectués par les pilotes de numéro 100
et 204 ?
R9.1 = ……………………………………………………………………………………………………………………………………………………
R9.2 = ……………………………………………………………………………………………………………………………………………………
R9.3 = ……………………………………………………………………………………………………………………………………………………
R9 = …………..…………………………………………………………………………………………………………………………………………
Q10 : Donnez le numéro des vols effectués au départ de Nice par des pilotes Niçois ?
R10.1 = ……………………………………………………………………………………………………………………………………………………
R10.2 = ……………………………………………………………………………………………………………………………………………………
R10 = …………………..…………………………………………………………………………………………………………………………………
Q11 : Quels sont les vols effectués par un avion qui n'est pas localisé à Nice ?
R11.1 = ……………………………………………………………………………………………………………………………………………………
R11.2 = ……………………………………………………………………………………………………………………………………………………
R11 = ………..……………………………………………………………………………………………………………………………………………
Q12 : Quels sont les pilotes (numéro et nom) assurant au moins un vol au départ de Nice
avec un avion de capacité supérieure à 300 places ?
R12.1 = ……………………………………………………………………………………………………………………………………………………
R12.2 = ……………………………………………………………………………………………………………………………………………………
R12.3 = ……………………………………………………………………………………………………………………………………………………
R12 = ………………….……………………………………………………………………………………………………………………………………
Q13 : Quels sont les noms des pilotes domiciliés à Paris assurant un vol au départ de Nice
avec un Airbus ?
19
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
R13.1 = ……………………………………………………………………………………………………………………………………………………
R13.2 = ……………………………………………………………………………………………………………………………………………………
R13.3 = ……………………………………………………………………………………………………………………………………………………
R13 = ……………………………………….………………………………………………………………………………………………………………
Q14 : Quels sont les numéros des vols effectués par un pilote Niçois au départ ou à
l'arrivée de Nice avec un avion localisé à Paris ?
R14.1 = ……………………………………………………………………………………………………………………………………………………
R14.2 = ……………………………………………………………………………………………………………………………………………………
R14.3 = ……………………………………………………………………………………………………………………………………………………
R14.4 = ……………………………………………………………………………………………………………………………………………………
R14.5 = ……………………………………………………………………………………………………………………………………………………
R14 = ……………………………………………………………………………………………………………………………………………………
Q15 : Quels sont les pilotes (numéro et nom) habitant dans la même ville que le pilote Dupont
?
Q16 : Quels sont les numéros des pilotes en service différents de celui de Durand ?
Q17 : Quelles sont les villes desservies à partir de la ville d'arrivée d'un vol au départ de
Paris ?
Q18 : Quels sont les appareils (leur numéro) localisés dans la même ville que l'avion numéro
100 ?
Exercice 4 : Divers
Q19 : Quels sont les numéros et noms des pilotes domiciliés dans la même ville que le pilote
Dupont et dont le salaire est supérieur à celui de Dupont ?
Q20 : Quels sont les numéros et noms des pilotes qui effectuent un vol au départ de leur
ville de résidence ?
Q21 : Y a-t-il des homonymes parmi les pilotes ? Si oui, donner leur numéro et nom.
Q22 : Quels sont les pilotes bordelais ne pilotant que des avions arrivant au moins une fois
à Bordeaux ?
20
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
2.1. Définition
SQL est un langage de définition de données (LDD, ou en anglais DDL Data Definition
Language), un langage de manipulation de données (LMD, ou en anglais DML, Data
Manipulation Language), et un langage de contrôle de données (LCD, ou en anglais DCL, Data
Control Language), pour les bases de données relationnelles.
La projection (SELECT………FROM)
L’utilisation la plus courante de SQL consiste à lire des données issues de la base de
données. Cela s’effectue grâce à la commande SELECT, qui retourne des enregistrements
dans un tableau de résultat. Cette commande peut sélectionner une ou plusieurs colonnes
d’une table.
Syntaxe :
SQL AS (alias)
Dans le langage SQL il est possible d’utiliser des alias pour renommer temporairement une
colonne ou une table dans une requête. Cette astuce est particulièrement utile pour
faciliter la lecture des requêtes.
Alias sur une colonne Permet de renommer le nom d’une colonne dans les résultats d’une
requête SQL. C’est pratique pour avoir un nom facilement identifiable dans une application
qui doit ensuite exploiter les résultats d’une recherche
Syntaxe :
La selection (SELECT…….FROM…………..WHERE)
21
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
SQL WHERE La commande WHERE dans une requête SQL permet d’extraire les lignes
d’une base de données qui respectent une condition. Cela permet d’obtenir uniquement les
informations désirées.
SELECT nom_colonnes
FROM nom_table
WHERE condition ;
Opérateur Description
= Égale
Pas égale
!= Pas égale
> Supérieur à
< Inférieur à
22
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
SELECT nom_colonnes
FROM nom_table
WHERE condition1 AND condition2
Ces opérateurs peuvent être combinés à l’infini et mélangés. L’exemple ci-dessous filtre les
résultats de la table « nom_table » si condition1 ET condition2 OU condition3 est vrai :
Attention : il faut penser à utiliser des parenthèses lorsque c’est nécessaire. Cela permet
d’éviter les erreurs car et ça améliore la lecture d’une requête par un humain.
SQL IN
L’opérateur logique IN dans SQL s’utilise avec la commande WHERE pour vérifier si une
colonne est égale à une des valeurs comprises dans set de valeurs déterminés. C’est une
méthode simple pour vérifier si une colonne est égale à une valeur OU une autre valeur OU
une autre valeur et ainsi de suite, sans avoir à utiliser de multiple fois l’opérateur OR.
Syntaxe Pour chercher toutes les lignes où la colonne « nom_colonne » est égale à ‘valeur
1′ OU ‘valeur 2′ ou ‘valeur 3′, il est possible d’utiliser la syntaxe suivante :
SELECT nom_colonne
FROM table
WHERE nom_colonne IN ( valeur1, valeur2, valeur3, ... )
SQL BETWEEN
L’opérateur BETWEEN est utilisé dans une requête SQL pour sélectionner un intervalle de
données dans une requête utilisant WHERE. L’intervalle peut être constitué de chaînes de
caractères, de nombres ou de dates. L’exemple le plus concret consiste par exemple à
récupérer uniquement les enregistrements entre 2 dates définies.
SELECT *
FROM table
WHERE nom_colonne BETWEEN 'valeur1' AND 'valeur2'
23
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
SQL LIKE
L’opérateur LIKE est utilisé dans la clause WHERE des requêtes SQL. Ce mot-clé permet
d’effectuer une recherche sur un modèle particulier. Il est par exemple possible de
rechercher les enregistrements dont la valeur d’une colonne commence par telle ou telle
lettre. Les modèles de recherches sont multiples.
Syntaxe La syntaxe à utiliser pour utiliser l’opérateur LIKE est la suivante :
SELECT *
FROM table
WHERE colonne LIKE modele
Dans cet exemple le « modèle » n’a pas été défini, mais il ressemble très généralement à
l’un des exemples suivants : LIKE ‘%a’ : le caractère « % » est un caractère joker qui
remplace tous les autres caractères. Ainsi, ce modèle permet de rechercher toutes les
chaines de caractère qui se termine par un « a ».
o LIKE ‘a%’ : ce modèle permet de rechercher toutes les lignes de « colonne » qui
commence par un « a ».
o LIKE ‘%a%’ : ce modèle est utilisé pour rechercher tous les enregistrements qui
utilisent le caractère « a ».
o LIKE ‘pa%on’ : ce modèle permet de rechercher les chaines qui commence par « pa »
et qui se terminent par « on », comme « pantalon » ou « pardon ».
o LIKE ‘a_c’ : peu utilisé, le caractère « _ » (underscore) peut être remplacé par
n’importe quel caractère, mais un seul caractère uniquement (alors que le symbole
pourcentage « % » peut être remplacé par un nombre incalculable de caractères . Ainsi,
ce modèle permet de retourner les lignes « aac », « abc » ou même « azc ».
Syntaxe Pour filtrer les résultats où les champs d’une colonne sont à NULL il convient
d’utiliser la syntaxe suivante :
SELECT *
FROM `table`
WHERE nom_colonne IS NULL
A l’inverse, pour filtrer les résultats et obtenir uniquement les enregistrements qui ne sont
pas null, il convient d’utiliser la syntaxe suivante :
SELECT *
FROM `table`
WHERE nom_colonne IS NOT NULL
24
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
A savoir : l’opérateur IS retourne en réalité un booléen, c’est à dire une valeur TRUE si la
condition est vraie ou FALSE si la condition n’est pas respectée. Cet opérateur est souvent
utilisé avec la condition WHERE mais peut aussi trouver son utilité lorsqu’une sous-requête
est utilisée.
SQL GROUP BY
La commande GROUP BY est utilisée en SQL pour grouper plusieurs résultats et utiliser
une fonction de totaux sur un groupe de résultat. Sur une table qui contient toutes les
ventes d’un magasin, il est par exemple possible de lister, regrouper les ventes par clients
identiques et d’obtenir le coût total des achats pour chaque client.
Syntaxe d’utilisation de GROUP BY De façon générale, la commande GROUP BY s’utilise de
la façon suivante :
A noter : cette commande doit toujours s’utiliser après la commande WHERE et avant la
commande HAVING.
Prenons en considération une table “achat” qui résume les ventes d’une boutique :
2 Simon 47 2012-10-27
3 Marie 18 2012-11-05
4 Marie 20 2012-11-14
Ce tableau contient une colonne qui sert d’identifiant pour chaque ligne, une autre qui
contient le nom du client, le coût de la vente et la date d’achat.
Pour obtenir le coût total de chaque client en regroupant les commandes des mêmes clients,
il faut utiliser la requête suivante :
25
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
Simon 47
Marie 38
Résultat :
client SUM(tarif)
Pierre 262
Simon 47
Marie 38
Marie 38
Pierre 262
Utilisation d’autres fonctions de statistiques Il existe plusieurs fonctions qui peuvent être
utilisées pour manipuler plusieurs enregistrements, il s’agit des fonctions d’agrégations
statistiques, les principales sont les suivantes :
o AVG() pour calculer la moyenne d’un set de valeur. Permet de connaître le prix du
panier moyen pour de chaque client
o COUNT() pour compter le nombre de lignes concernées. Permet de savoir combien
d’achats a été effectué par chaque client
o MAX() pour récupérer la plus haute valeur. Pratique pour savoir l’achat le plus cher
o MIN() pour récupérer la plus petite valeur. Utile par exemple pour connaître la date
du premier achat d’un client
o SUM() pour calculer la somme de plusieurs lignes. Permet par exemple de connaître
le total de tous les achats d’un client Ces petites fonctions se révèlent rapidement
indispensable pour travailler sur des données.
26
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
SQL HAVING
La condition HAVING en SQL est presque similaire à WHERE à la seule différence que
HAVING permet de filtrer en utilisant des fonctions telles que SUM(), COUNT(), AVG(),
MIN() ou MAX().
Syntaxe L’utilisation de HAVING s’utilise de la manière suivante :
Important : HAVING est très souvent utilisé en même temps que GROUP BY bien que ce
ne soit pas obligatoire
Exemple
Pour utiliser un exemple concret, imaginons une table “achat” qui contient les achats de
différents clients avec le coût du panier pour chaque achat.
2 Simon 47 2012-10-27
3 Marie 18 2012-11-05
4 Marie 20 2012-11-14
Si dans cette table on souhaite récupérer la liste des clients qui ont commandé plus de 40€,
toute commandes confondues alors il est possible d’utiliser la requête suivante :
27
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
Résultat :
client SUM(tarif)
Pierre 262
Simon 47
La cliente “Marie” a cumulé 38€ d’achat (un achat de 18€ et un autre de 20€) ce qui est
inférieur à la limite de 40€ imposée par HAVING. En conséquent cette ligne n’est pas
affichée dans le résultat.
SQL ORDER BY
La commande ORDER BY permet de trier les lignes dans un résultat d’une requête SQL. Il
est possible de trier les données sur une ou plusieurs colonnes, par ordre ascendant ou
descendant.
Syntaxe Une requête où l’on souhaite filtrer l’ordre des résultats utilise la commande
ORDER BY de la sorte :
Par défaut les résultats sont classés par ordre ascendant, toutefois il est possible
d’inverser l’ordre en utilisant le suffixe DESC après le nom de la colonne. Par ailleurs, il est
possible de trier sur plusieurs colonnes en les séparant par une virgule. Une requête plus
élaborée ressemblerait alors cela :
A noter : il n’est pas obligé d’utiliser le suffixe « ASC » sachant que les résultats sont
toujours classés par ordre ascendant par défaut. Toutefois, c’est plus pratique pour mieux
s’y retrouver, surtout si on a oublié l’ordre par défaut.
En utilisant deux méthodes de tri, il est possible de tri la première colonne puis de trier
une deuxième colonne selon le premier tri.
La requête serait alors la suivante :
SELECT *
FROM utilisateur
ORDER BY nom, date_inscription DESC
28
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
Une requête SELECT peut devenir assez longue. Juste à titre informatif, voici une requête
SELECT qui possède presque toutes les commandes possibles :
SELECT *
FROM table
WHERE condition
GROUP BY expression
HAVING condition
{ UNION | INTERSECT | EXCEPT }
ORDER BY expression
SQL UNION
La commande UNION de SQL permet de mettre bout-à-bout les résultats de plusieurs
requêtes utilisant elles-mêmes la commande SELECT. C’est donc une commande qui permet
de concaténer les résultats de 2 requêtes ou plus. Pour l’utiliser il est nécessaire que
chacune des requêtes à concaténer retournes le même nombre de colonnes, avec les mêmes
types de données et dans le même ordre.
A savoir : par défaut, les enregistrements exactement identiques ne seront pas répétés
dans les résultats. Pour effectuer une union dans laquelle même les lignes dupliquées sont
affichées il faut plutôt utiliser la commande UNION ALL.
Syntaxe La syntaxe pour unir les résultats de 2 tableaux sans afficher les doublons est la
suivante :
SQL INTERSECT
La commande SQL INTERSECT permet d’obtenir l’intersection des résultats de 2
requêtes. Cette commande permet donc de récupérer les enregistrements communs à 2
requêtes. Cela peut s’avérer utile lorsqu’il faut trouver s’il y a des données similaires sur 2
tables distinctes.
A savoir : pour l’utiliser convenablement il faut que les 2 requêtes retournent le même
nombre de colonnes, avec les mêmes types et dans le même ordre.
Syntaxe La syntaxe à adopter pour utiliser cette commande est la suivante :
29
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
Dans cet exemple, il faut que les 2 tables soient similaires (mêmes colonnes, mêmes types
et même ordre). Le résultat correspondra aux enregistrements qui existent dans table1 et
dans table2.
A savoir : cette commande s’appelle différemment selon les Systèmes de Gestion de Base
de Données (SGBD) :
o EXCEPT : PostgreSQL
o MINUS : MySQL et Oracle
Dès lors, il faut remplacer tout le reste de ce cours par MINUS pour les SGBD
correspondants.
Cette requête permet de lister les résultats du table 1 sans inclure les enregistrements de
la table 1 qui sont aussi dans la table 2.
Attention : les colonnes de la première requête doivent être similaires entre la première
et la deuxième requête (même nombre, même type et même ordre).
Jointure SQL
Les jointures en SQL permettent d’associer plusieurs tables dans une même requête. Cela
permet d’exploiter la puissance des bases de données relationnelles pour obtenir des
résultats qui combinent les données de plusieurs tables de manière efficace.
Types de jointures
Il y a plusieurs méthodes pour associer 2 tables ensemble. Voici la liste des différentes
techniques qui sont utilisées :
INNER JOIN : jointure interne pour retourner les enregistrements quand la
condition est vraie dans les 2 tables. C’est l’une des jointures les plus communes.
CROSS JOIN : jointure croisée permettant de faire le produit cartésien de 2
tables. En d’autres mots, permet de joindre chaque ligne d’une table avec chaque
ligne d’une seconde table. Attention, le nombre de résultats est en général très
élevé.
30
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
LEFT JOIN (ou LEFT OUTER JOIN) : jointure externe pour retourner tous les
enregistrements de la table de gauche (LEFT = gauche) même si la condition n’est
pas vérifiée dans l’autre table.
RIGHT JOIN (ou RIGHT OUTER JOIN) : jointure externe pour retourner tous
les enregistrements de la table de droite (RIGHT = droite) même si la condition
n’est pas vérifiée dans l’autre table.
FULL JOIN (ou FULL OUTER JOIN) : jointure externe pour retourner les
résultats quand la condition est vraie dans au moins une des 2 tables.
SELF JOIN : permet d’effectuer une jointure d’une table avec elle-même comme
si c’était une autre table.
NATURAL JOIN : jointure naturelle entre 2 tables s’il y a au moins une colonne
qui porte le même nom entre les 2 tables SQL
UNION JOIN : jointure d’union
Syntaxes :
31
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
32
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
Savoir-faire :
33
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
Durée : CM ----------------------------------------------------------------------------------(2H)
3.1. Introduction
Deux algorithmes produisant les mêmes résultats peuvent être très différents du point de
vu des méthodes utilisées, de leurs complexités apparentes et de leurs efficacités.
Retenons que l’efficacité d’un algorithme est son coût en termes de temps d’exécution et
de mémoire. On évalue l’efficacité d’un algorithme par son coût qui dépend de deux
paramètres essentiels :
- Sa durée d’exécution appelé aussi complexité temporelle qui est liée au nombre
d’opération effectué par l’algorithme
- L’espace mémoire requis appelé aussi complexité spatiale qui est l’encombrement
mémoire.
Le problème que nous nous attelons à résoudre dans ce chapitre est le suivant : de deux
algorithmes résolvant le même problème, lequel choisir ?
3.2. Motivations
Méthode 1
def y(x,n) :
if (x !=0 and n == 0) :
return 1
else :
return x*y(x,n-1)
Méthode 2
𝑦(𝑥, 0) = 1
𝑦(𝑥, 𝑛) = y(x, n/2) ∗ y(x, n/2) si n est paire
𝑦(𝑥, 𝑛) = y(x, (n − 1)/2) ∗ y(x, (n − 1)/2) ∗ x si n est impaire
34
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
def y(x,n) :
if (x != 0 ande n == 0) :
return 1
elif n mod 2 == 0 :
return y(x,n/2)* y(x,n/2)
else:
return x*y(x,(n-1)/2)*y(x,(n-1)/2)
Réponse : la deuxième car elle permet d’effectuer moins de produit que la première.
Dans la pratique, la durée d’exécution dépend de la taille et de la valeur des données. Par
exemple, dans le cas d’un algorithme de tri, si les valeurs sont partiellement triées ou trié
à l’envers, le temps de traitement peut varier de façon significative.
On pourra donc définir trois sortes de complexité temporelles :
- La Complexité maximale : C’est le temps d’exécution d’un algorithme dans le cas le plus
défavorable. (Exemple : lorsque le n est très grand)
- La Complexité moyenne : c’est le temps d’exécution moyenne de l’algorithme
- La Complexité dans le meilleur des cas : le temps d’exécution le plus court. On calcul
la complexité dans le meilleur des cas. (Exemple : lorsque la valeur de n vaut 0)
Remarques :
o Dans la pratique, on étudie souvent le pire des cas, ce qui donne une borne supérieure
de la complexité de l’algorithme.
o La complexité maximale et moyenne d’un algorithme sont généralement équivalents.
o Lorsqu’on évalue la complexité d’un algorithme, on ne s’intéresse pas au temps de
calcul réel mais à un ordre de grandeur.
3.3.1. Définition 2
Nous notons Dn l’ensemble des données de taille n et T(d) le coût de l’algorithme sur la
donnée d.
35
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
Complexité au meilleur : Tmin(n) = mind∈Dn C(d). C’est le plus petit nombre d’opérations
qu’aura à exécuter l’algorithme sur un jeu de données de taille fixée, ici à n. C’est une borne
inférieure de la complexité de l’algorithme sur un jeu de données de taille n.
Complexité au pire : Tmax(n) = maxd∈Dn C(d). C’est le plus grand nombre d’opérations qu’aura
à exécuter l’algorithme sur un jeu de données de taille fixée, ici à n.
Avantage : il s’agit d’un maximum, et l’algorithme finira donc toujours avant d’avoir effectué
Tmax(n) opérations.
Inconvénient : cette complexité peut ne pas refléter le comportement « usuel » de
l’algorithme, le pire des cas pouvant ne se produire que très rarement, mais il n’est pas rare
que le cas moyen soit aussi mauvais que le pire des cas.
36
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
Exemple 1 :
Coût Nombre
de fois
Procedure TriInsertion(T:Tableau)
Const n 8 : Entier #Taille du tableau
Var
i, j, Temp : Entier
Debut
Complexité au meilleur : le cas le plus favorable pour l’algorithme TriInsertion est quand le
tableau est déjà trié. Dans ce cas tj = 1 pour tout j.
T(n) peut ici être écrit sous la forme T(n) = an + b, a et b étant des constantes
indépendantes des entrées.
𝐓(𝒏) = 𝑶(𝒏) est donc une fonction linéaire de n.
Le plus souvent, comme c’est le cas ici, le temps d’exécution d’un algorithme est fixé pour
une entrée donnée ; mais il existe des algorithmes « aléatoires » intéressants dont le
comportement peut varier même pour une entrée fixée. Nous verrons un algorithme de ce
style dans la suite du cours : une version « aléatoire » du tri rapide.
Complexité au pire : le cas le plus défavorable pour l’algorithme TriInsertion est quand le
tableau est déjà trié dans l’ordre inverse, comme le montre le cas j = 5 de la figure 2.1.
Dans ce cas t j = j pour tout j.
37
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
T(n) peut ici être écrit sous la forme T(n) = a*n2 + b*n + c, a, b et c étant des constantes.
𝑻(𝒏) = 𝑶(𝒏𝟐 ).T(n) est donc une fonction quadratique de n.
Complexité en moyenne : supposons que l’on applique l’algorithme de tri par insertion à n
nombres choisis au hasard. Quelle sera la valeur de t j ? C’est-à-dire, où devra-t-on insérer
A[j] dans le sous-tableau A[1.. j − 1] ?
En moyenne, pour moitié les éléments de A[1.. j − 1] sont inférieurs à A[j], et pour moitié
supérieurs.
Donc tj = j/2. Si l’on reporte cette valeur dans l’équation définissant T(n), on obtient, comme
dans le pire cas, une fonction quadratique en n.
O(1) Constant
O(log(n)) Logarithmique
O(n) Linéaire
O(n*log(n)) Quasi-linéaire
O(n2) Quadratique
Ο(n3) Cubique
Ο(2n) Exponentiel
Ο(n!) Factoriel
38
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
Définition
Une pile est une structure de données mettant en œuvre le principe « dernier entré,
premier sorti » (LIFO : Last-In, First-Out en anglais).
L’élément ôté de l’ensemble par l’opération SUPPRESSION est spécifié à l’avance (et donc
cette opération ne prend alors que l’ensemble comme argument) : l’élément supprimé est
celui le plus récemment inséré. L’opération INSERTION dans une pile est communément
appelée EMPILER, et l’opération SUPPRESSION, DÉPILER. La figure 5.1 montre les
conséquences des opérations EMPILER et DÉPILER sur une pile.
4.3.1. Algorithme
Il est facile d’implémenter une pile au moyen d’un tableau. La seule difficulté dans
cette implémentation est la gestion des débordements de pile qui interviennent quand on
tente d’effecteur l’opération DÉPILER sur une pile vide et l’opération EMPILER sur un
tableau codant la pile qui est déjà plein. Ce dernier problème n’apparaît pas lorsque l’on
implémente les piles au moyen d’une structure de données dont la taille n’est pas fixée a
priori (comme une liste chaînée). Les algorithmes réalisant les fonctions EMPILER et
DÉPILER, ainsi que la nécessaire fonction auxiliaire PILE-VIDE, sont présentés
Procedure PileVide(P)
Debut
Si sommet(P)==0 Alors
Retourner Vrai
Sinon
Retourner Faux
Finsi
Fin.
39
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
40
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
4.4. Applications
Dans un navigateur web, une pile sert à mémoriser les pages Web visitées. L’adresse de
chaque nouvelle page visitée est empilée et l’utilisateur désempile l’adresse de la page
précédente en cliquant sur le bouton « Afficher la page précédente ».
La fonction « annuler la frappe » (en anglais "undo") d’un traitement de texte mémorise les
modifications apportées au texte dans une pile et permet ainsi de revenir en arrière pas à
pas.
Un algorithme de recherche en profondeur utilise une pile pour mémoriser les nœuds
visités. On peut inverser les éléments contenus dans un tableau ou dans une chaîne de
caractères en utilisant une pile. Il suffit d’empiler les éléments sur une pile puis de
reconstituer le tableau (ou la chaîne) inverse en désempilant les éléments. L’évaluation des
expressions mathématiques en notation post-fixée (ou notation polonaise inverse) utilise
une pile.
41
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
Durée : CM ---------------------------------------------------------------------------------(2H)
5.1. Introduction
Une définition récursive est une définition dans laquelle intervient ce que l’on veut définir.
Un algorithme est dit récursif lorsqu’il est défini en fonction de lui-même.
Dans le cadre de ce cours, nous ne nous intéresserons qu’aux programmes et algorithmes
récursifs. Mais la notion de définition récursive est beaucoup plus générale : en
mathématiques on parle de récurrence alors qu’en programmation on parle de récursivité.
Récursivité simple
Revenons à la fonction puissance x → xn. Cette fonction peut être définie récursivement :
x 0 = 1 et ∀ n > 0, x n = x ∗ x n−1
def Power_1(x,n) :
if n == 0 :
return 1
else :
return x*Power_1(x,n-1)
Récursivité multiple
Une définition récursive peut contenir plus d’un appel récursif.
x0 = 1
x n = x n/2 ∗ x n/2 si n est paire
x n = x (n−1)/2 ∗ x (n−1)/2 ∗ x si n est impaire
def Power_2(x,n) :
if n == 0 :
return 1
elif n mod 2 == 0 :
return Power_2(x,n/2)* Power_2(x,n/2)
else:
return x*Power_2(x,(n-1)/2)*Power_2(x,(n-1)/2)
Récursivité mutuelle
Des définitions sont dites mutuellement récursives si elles dépendent les unes des autres.
Ça peut être le cas pour la définition de la parité :
42
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
def Pair(n) :
if n == 0 :
return True
else:
return Impair(n-1)
def Impair(n):
if n == 0 :
return False
else:
return Pair(n-1)
Récursivité imbriquée
La fonction d’Ackermann est définie comme suit :
def Ackermann(m,n):
if m == 0:
return n+1
elif n > 0 and n == 0:
return Ackermann(m-1,1)
else:
return Ackermann(m-1,Ackermann(m,n-1))
Exemple 2 :
Chez les prêtes d’une certaine secte religieuse, on a résolu le problème suivant : 64 disques
posés les uns sur les autres sur un socle A, on les transférer sur un socle C en utilisant un
socle B. les seuls déplacements possibles consistent à prendre un disque sur le sommet, à
le poser sur les autres socles vides ou sur un disque plus grand que lui.
Selon la légende, la fin du monde coïncidera avec la résolution du problème !!!
Analyse du problème
Paramétrage
Soient :
n : Le nombre de disque
D : socle de départ
A : socle d’arrivé
I : socle intermédiaire
43
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
Cas triviaux
Si n = 0 ne rien faire
Si n = 1 déplacer sur le socle A Deplace(D,A)
Complexité de l’algorithme
0, n=0
T(n) = {
1 + 2T(n − 1), n≥1
Pour n = 64 on a : T(64) = 18 446 744 073 709 551 615 nombre de déplacements
Pour un déplacement de 1 seconde on finira en 584 942 417 355 ans voire la fin du monde !!!!
44
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
Théorème 1 :
45
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
Durée : CM ---------------------------------------------------------------------------(4H)
6.1. Introduction
Les algorithmes de tri ont une grande importance pratique. Ils sont fondamentaux dans
l’informatique où l’on tri de manière quasi-systématique des données avant de les utiliser.
L’étude du tri est également intéressante en elle-même car il s’agit sans doute du
domaine de l’algorithmique qui a été le plus étudié et qui a conduit à des résultats
remarquables sur la construction d’algorithmes et l’étude de leur complexité.
Les exemples de tris que nous étudierons dans ce cours vous permettrons de vous forger
une idée. Il y a bien sûr d’autres algorithmes que ceux présentés ici, mais ce document n’a
pas l’ambition de dresser une liste exhaustive de ce qui existe mais d’avoir un
aperçu de ce problème qui est plus complexe qui n’y paraît au premier abord.
Tout le monde est confronté un jour ou l’autre à trier des affaires et l’on sait que
c’est loin d’être facile.
C’est le tri du joueur de cartes. On fait comme si les éléments à trier étaient donnés un
par un, le premier élément constituant, à lui tout seul, une liste triée de longueur 1. On
range ensuite le second élément pour constituer une liste triée de longueur 2, puis on range
le troisième élément pour avoir une liste triée de longueur 3 et ainsi de suite ....
À chaque itération , on place l’élément à sa place en décalant ceux qui sont plus
grands.
Le principe du tri par insertion est donc d’insérer à la nième itération le nième élément à la
bonne place.
46
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
0 86 8 79 21 58 49 42 22 28 79
1 8 86 79 21 58 49 42 22 28 79
2 8 79 86 21 58 49 42 22 28 79
3 8 21 79 86 58 49 42 22 28 79
4 8 21 58 79 86 49 42 22 28 79
5 8 21 49 58 79 86 42 22 28 79
6 8 21 42 49 58 79 86 22 28 79
7 8 21 22 42 49 58 79 86 28 79
8 8 21 22 28 42 49 58 79 86 79
9 8 21 22 28 42 49 58 79 79 86
Voici les étapes de l'exécution du tri par insertion sur le tableau T = [9,6,1,4,8]. Le tableau
est représenté au début et à la fin de chaque itération.
47
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
La complexité du tri par insertion est Θ(n2) dans le pire cas et en moyenne, et linéaire dans
le meilleur cas. Plus précisément :
1. Dans le pire cas, atteint lorsque le tableau est trié à l'envers, l'algorithme effectue
de l'ordre de n2/2 affectations et comparaisons ;
2. Si les éléments sont distincts et que toutes leurs permutations sont équiprobables
(c’est-à-dire avec une distribution uniforme), la complexité en moyenne de
l'algorithme est de l'ordre de n2/4 affectations et comparaisons2 ;
3. Si le tableau est déjà trié, il y a n-1 comparaisons et au plus n affectations.
Dans le pire des cas le nombre de comparaisons "TantQue (j>0 etTab[ j-1 ] > x) Faire" est
une valeur qui ne dépend que de la longueur i de la partie (T[1], T[2], …T[i]) déjà rangée. Il
y a donc au pire i comparaisons pour chaque i variant de 1 à n-1 :
La complexité au pire en nombre de comparaison est donc égale à la somme des n termes
suivants (i = 1, i = 2,.... i = n-1)
C = 1+2 + 3 + 4 +...+ n-1 = n(n-1)/2 comparaisons au maximum.
La complexité au pire en nombre de comparaison est de de l'ordre de n², que l'on écrit
O(n²).
La complexité du tri par insertion reste linéaire si le tableau est presque trié (par exemple,
chaque élément est à une distance bornée de la position où il devrait être, ou bien tous les
éléments sauf un nombre borné sont à leur place). Dans cette situation particulière, le tri
par insertion surpasse d'autres méthodes de tri. Lesquels ? A répondre à la fin du cours
sur les tris.
En informatique, le tri rapide (en anglais quicksort) est un algorithme de tri inventé
par inventé par Charles Antony R. Hoare en 1961 et amélioré par Robert Sedgewick dans
les années 70 et fondé sur la méthode de conception diviser pour régner. Il est
généralement utilisé sur des tableaux, mais peut aussi être adapté aux listes
Le tri rapide est l’un des tris les plus rapide et donc l’un des plus utilisé. Cependant ce tri
ne peut pas tirer avantage du fait que l’entrée est déjà presque triée.
Dans ce cas particulier, il est plus avantageux d’utiliser le tri par insertion.
48
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
Fonction Partitionnement
49
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
• Pivot arbitraire
Une manière simple de choisir le pivot est de prendre toujours le premier élément du sous-
tableau courant (ou le dernier). Lorsque toutes les permutations possibles des entrées
sont équiprobables, la complexité moyenne du tri rapide en sélectionnant le pivot de cette
façon est Θ(n log (n)). Cependant, la complexité dans le cas le pire est Θ(n2), et celle-ci est
atteinte lorsque l'entrée est déjà triée ou presque triée.
Si on prend comme pivot le milieu du tableau, le résultat est identique, bien que les entrées
problématiques soient différentes.
Il est possible d'appliquer une permutation aléatoire au tableau pour éviter que
l'algorithme soit systématiquement lent sur certaines entrées. Cependant, cette technique
est généralement moins efficace que de choisir le pivot aléatoirement.
• Pivot aléatoire
Si on utilise la méthode donnée dans la description de l'algorithme, c'est-à-dire choisir le
pivot aléatoirement de manière uniforme parmi tous les éléments, alors la complexité
moyenne du tri rapide est Θ(n log (n)) sur n'importe quelle entrée. Dans le pire des cas, la
complexité est Θ(n2). Néanmoins, l'écart type de la complexité est seulement Θ(n), ce qui
signifie que l'algorithme s'écarte peu du temps d'exécution moyen.
Dans le cas le meilleur, l'algorithme est en Θ(n log (n)).
À partir de deux listes triées, on peut facilement construire une liste triée comportant les
éléments issus de ces deux listes (leur *fusion*). Le principe de l'algorithme de tri fusion
repose sur cette observation : le plus petit élément de la liste à construire est soit le plus
50
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
petit élément de la première liste, soit le plus petit élément de la deuxième liste. Ainsi, on
peut construire la liste élément par élément en retirant tantôt le premier élément de la
première liste, tantôt le premier élément de la deuxième liste (en fait, le plus petit des
deux, à supposer qu'aucune des deux listes ne soit vide, sinon la réponse est immédiate).
Ce procédé est appelé fusion et est au cœur de l'algorithme de tri développé ci-après.
51
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
52
Classes Préparatoires
aux Grandes Ecoles
Approfondissement en Python 3
Le tri fusion comporte 3 étapes : la division de l’ensemble d’éléments en deux parties, le tri
des deux sous-ensembles puis la fusion des deux sous-ensembles triés. Soit un ensemble
de n éléments, le coût en nombre d’opérations de la division des deux ensembles est
constant dans le cas du tri de tableaux et est de n dans le cas des listes. Le coût du tri des
deux sous listes est égal à 2 fois le coût du tri d’une liste de longueur n/2. Enfin, le coût de
la fusion des deux sous listes triées est proportionnel au nombre d’éléments à fusionner,
c’est à dire en O(n).
Les quelques algorithmes vus jusqu’à maintenant sont en O(n2). D’après les résultats ci-
dessus, si on note T(n) la complexité du tri fusion pour classer n éléments, on a :
Ce qui est inférieur à n2 dès que n>2. Par conséquent, la complexité du tri fusion n’est pas
en O(n2) mais en une valeur bien inférieure.
Pour calculer la complexité du tri fusion, nous avons besoin du résultat du théorème 1.
Soit T(n) une suite vérifiant la relation de récurrence suivante :
➢ T(n)=aT(n/b)+O(nc).
➢ Si a < bc alors T(n)=O(nc)
➢ Si a = bc alors T(n)=O(nclogb(n))
➢ Si a > bc alors T(n)=O(nlogb(a)) avec logb le logarithme népérien en base b
Ici, on a (2 = 21), la complexité du tri fusion est donc en O(n*ln(n)) ou ln(n) est le logarithme
népérien en base 2.
Remarque : en ce qui concerne le tri de listes, le tri fusion souffre du fait que c’est un
algorithme récursif. En effet, pour se dérouler, il doit construire un grand nombre de sous
listes, ce qui demande un grand espace mémoire. La complexité en espace mémoire du tri
fusion est donc assez handicapante si l’espace mémoire disponible n’est pas assez grand.
TDn°4 – Tri rapide, tri fusion, complexité de tris avancés ---------------- (4H)
TPn°5 – Implémentation de Tris avancés : tri rapide, tri fusion ------------ (2H)
53