méthodes de tri rapide en python
This commit is contained in:
parent
bf45ad7859
commit
b5b00ce4d3
|
@ -1,20 +0,0 @@
|
|||
les types structurés
|
||||
- le produit cartésien
|
||||
- le n-uplet
|
||||
- types produits nommés (enregistrements)
|
||||
|
||||
type complexe = { re : float; im : float} ;;
|
||||
type complexe = { re : float; im : float; }
|
||||
# let a = {re=1.4; im = 0.5} ;;
|
||||
val a : complexe = {re = 1.4; im = 0.5}
|
||||
# a.re ;;
|
||||
- : float = 1.4
|
||||
# a.im ;;
|
||||
- : float = 0.5
|
||||
|
||||
les types sommes : modélisation de domaines finis
|
||||
# type couleur = Pique | Coeur | Carreau | Trefle;;
|
||||
type couleur = Pique | Coeur | Carreau | Trefle
|
||||
# let a = Trefle ;;
|
||||
val a : couleur = Trefle
|
||||
|
|
@ -197,6 +197,8 @@ Description de l'algorithme
|
|||
- la fonction inserer permet d’insérer un élément x dans une liste l
|
||||
- si la liste l est triée alors x est inséré au bon endroit
|
||||
|
||||
.. important:: la manière naturelle d'implémenter cet algorithme est ici la récursivité
|
||||
|
||||
.. code-block:: ocaml
|
||||
|
||||
# let rec inserer x l =
|
||||
|
@ -219,15 +221,21 @@ soit une liste l à trier :
|
|||
qui sont plus petits (resp. plus grands) que la valeur du pivot p
|
||||
- trier récursivement g et d, on obtient deux listes g’ et d’ triées
|
||||
|
||||
la fonction suivante permet de partager une liste l en deux sous-listes g et
|
||||
d contenant les éléments de l plus petits (resp. plus grands) qu’une valeur
|
||||
donnée p
|
||||
|
||||
.. code-block:: ocaml
|
||||
:caption: fonction de partage d'une liste
|
||||
|
||||
#let rec partage p l =
|
||||
match l with
|
||||
[] -> ([] , [])
|
||||
|x::s -> let g,d = partage p s in
|
||||
if x<=p then (x::g , d) else (g , x::d) ;;
|
||||
[] -> ([] , [])
|
||||
|x::s -> let g,d = partage p s in
|
||||
if x<=p then (x::g , d) else (g , x::d) ;;
|
||||
|
||||
val partage : ’a -> ’a list -> ’a list * ’a list = <fun>
|
||||
|
||||
# partage 5 [1 ;9 ;7 ;3 ;2 ;4];;
|
||||
- : int list * int list = ([1 ; 3 ; 2 ; 4], [9 ; 7])
|
||||
|
||||
|
@ -236,14 +244,184 @@ soit une liste l à trier :
|
|||
|
||||
# let rec tri rapide l =
|
||||
match l with
|
||||
[] -> []
|
||||
| p::s -> let g , d = partage p s in
|
||||
(tri rapide g)@[p]@(tri rapide d) ;;
|
||||
[] -> []
|
||||
| p::s -> let g , d = partage p s in
|
||||
(tri rapide g)@[p]@(tri rapide d) ;;
|
||||
|
||||
val tri rapide : ’a list -> ’a list = <fun>
|
||||
|
||||
# tri rapide [5 ; 1 ; 9 ; 7 ; 3 ; 2 ; 4];;
|
||||
- : int list = [1 ; 2 ; 3 ; 4 ; 5 ; 7 ; 9]
|
||||
|
||||
|
||||
autre exemple de tri : le tri fusion. Il y en a d'autres.
|
||||
|
||||
|
||||
Le tri en python
|
||||
----------------
|
||||
|
||||
Pour comprendre comment marche le tri en Python, il faut comprendre que presque tout en Python est ordonnable car comparable
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> 1 > 0 # les nombres sont comparables
|
||||
True
|
||||
>>> 1 < 0
|
||||
False
|
||||
>>> "a" < "b" # les lettres, par ordre alphabetique
|
||||
True
|
||||
>>> True > False # les booléan (!)
|
||||
True
|
||||
>>> (1, 2) > (2, 1) # les iterables comparés, élément par élément dans l'ordre
|
||||
False
|
||||
>>> (1, 2) > [2, 1] # mais ils doivent être du même type
|
||||
True
|
||||
>>> {1:1} < {1:1, 0:0} # les dictionnaires, par nombre d'éléments
|
||||
True
|
||||
>>> "a" > 2 # si on mélange des types ça peut vide devenir bizarre
|
||||
True
|
||||
>>> 1j > 1 # PRESQUE tout est ordonnable
|
||||
Traceback (most recent call last):
|
||||
File "<ipython-input-11-ed3c013d3df8>", line 1, in <module>
|
||||
1j > 1
|
||||
TypeError: no ordering relation is defined for complex numbers
|
||||
|
||||
C’est ce qu’on appelle l’ordre naturel des éléments. Quand il n’y a pas d’ordre naturel évident (et que ce n’est pas une opération explicitement interdite comme avec les complexes),
|
||||
Python va comparer l’id (imaginez l’adresse en mémoire)
|
||||
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> class PersonnageDeLost(object):
|
||||
... pass
|
||||
...
|
||||
>>> mort1 = PersonnageDeLost()
|
||||
>>> mort2 = PersonnageDeLost()
|
||||
>>> mort1 < mort2
|
||||
True
|
||||
>>> id(mort1) # son id est plus petit, donc il est inférieur
|
||||
39611408
|
||||
>>> id(mort2)
|
||||
41720976
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
class PersonnageDeCityHunter(object):
|
||||
|
||||
def __init__(self, nom, erectopouvoir):
|
||||
self.nom = nom
|
||||
self.erectopouvoir = erectopouvoir
|
||||
|
||||
|
||||
def __lt__(self, other):
|
||||
# on doit retourner un booléan qui confirme ou infirme
|
||||
# l'opération "lt" ("lower than", c'est à dire "plus petit que")
|
||||
return self.erectopouvoir < other.erectopouvoir
|
||||
|
||||
def __gt__(self, other):
|
||||
# on doit retourner un booléan qui confirme ou infirme
|
||||
# l'opération "gt" ("greater than", c'est à dire "plus grand que")
|
||||
return self.erectopouvoir > other.erectopouvoir
|
||||
|
||||
# on peut faire la même chose pour les autres méthodes qui
|
||||
# concernent les opérateurs <=, >=, == et !=
|
||||
|
||||
>>> PersonnageDeCityHunter('Ryo Saeba', 99999) > PersonnageDeCityHunter('Mamouth', 1)
|
||||
True
|
||||
>>> PersonnageDeCityHunter('Ryo Saeba', 99999) < PersonnageDeCityHunter('Mamouth', 1)
|
||||
False
|
||||
|
||||
Ordonner une liste
|
||||
-------------------
|
||||
|
||||
Avec `sort()` Les éléments sont triés dans leur ordre naturel automatiquement, du plus petit au plus grand:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> l = ['b', 'a', 'c']
|
||||
>>> l.sort()
|
||||
>>> l
|
||||
['a', 'b', 'c']
|
||||
>>> l = [(2, 1), (1, 2), (7, 8), (2, 2), (2, 0), (2, 3)]
|
||||
>>> l.sort()
|
||||
>>> l # ordonne sur le premier élément, puis le second si il y a égalité
|
||||
[(1, 2), (2, 0), (2, 1), (2, 2), (2, 3), (7, 8)]
|
||||
>>> persos = [PersonnageDeCityHunter('Ryo Saeba', 99999), PersonnageDeCityHunter('Mamouth', 1), PersonnageDeCityHunter('Kaori', 0)]
|
||||
>>> persos.sort()
|
||||
>>> for perso in persos:
|
||||
... print perso.nom
|
||||
...
|
||||
Kaori
|
||||
Mamouth
|
||||
Ryo Saeba
|
||||
|
||||
et inversement:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> l = [1, 7, 3, 8]
|
||||
>>> l.sort(reverse=True)
|
||||
>>> l
|
||||
[8, 7, 3, 1]
|
||||
|
||||
`sort()` et `sorted()` acceptent toutes les deux les mêmes arguments. Ce que vous apprenez pour l’un vaut pour l’autre. La seul différence est que sort() retourne None et modifie sur place, tandis que sorted() retourne une nouvelle liste. sorted() est un peu moins performant.
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> sorted((1, 7, 3, 8), reverse=True)
|
||||
[8, 7, 3, 1]
|
||||
|
||||
Utilisations de tri personnalisés
|
||||
----------------------------------
|
||||
|
||||
Parfois on a besoin de trier sur quelque chose de plus complexe qu’une lettre ou un chiffre. Par exemple, vous avez des scores dans un dictionnaires. Un dictionnaire n’est pas ordonné. Si vous imprimez un classement, il faut en faire une liste de tuples :
|
||||
|
||||
::
|
||||
|
||||
>>> sorted(scores.items())
|
||||
[('Cunegonde', 3), ('Gertrude', 4), ('Robert', 2), ('Roger', 1)]
|
||||
|
||||
C’est là qu’intervient le paramètre key. key est très particulier, c’est un paramètre qui attend qu’on lui passe un callback, donc key attend qu’on lui passe une fonction.
|
||||
::
|
||||
|
||||
>>> def get_score(nom_et_score):
|
||||
... return nom_et_score[1] # retourne le 2nd element du tuple
|
||||
...
|
||||
>>> sorted(scores.items(), key=get_score) # on passe la fonction a key
|
||||
[('Roger', 1), ('Robert', 2), ('Cunegonde', 3), ('Gertrude', 4)]
|
||||
|
||||
|
||||
.. ifconfig:: exercice
|
||||
|
||||
classer des objets voiture en fonction de la puissance du moteur
|
||||
|
||||
autre exemple: ordonner des objets voitures selon leur coût d’entretien d’abord, et ensuite par coût d’achat.
|
||||
|
||||
|
||||
::
|
||||
|
||||
class Voiture(object):
|
||||
|
||||
def __init__(self, cout_entretien, cout_achat):
|
||||
self.cout_entretien = cout_entretien
|
||||
self.cout_achat = cout_achat
|
||||
|
||||
def __repr__(self):
|
||||
return "<Voiture E-{} / A-{}>".format(self.cout_entretien, self.cout_achat)
|
||||
|
||||
>>> voitures = [Voiture(10000, 10000), Voiture(50000, 10000), Voiture(10000, 60000)]
|
||||
>>> voitures
|
||||
[<Voiture E-10000 / A-10000>, <Voiture E-50000 / A-10000>, <Voiture E-10000 / A-60000>]
|
||||
>>> def get_entretien_achat(voiture):
|
||||
... return (voiture.cout_entretien, voiture.cout_achat)
|
||||
...
|
||||
>>> sorted(voitures, key=get_entretien_achat)
|
||||
[<Voiture E-10000 / A-10000>, <Voiture E-10000 / A-60000>, <Voiture E-50000 / A-10000>]
|
||||
|
||||
|
||||
Définition d'un itérateur
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -552,13 +730,17 @@ On les appelle enregistrements, dictionnaires ou tables de hachage.
|
|||
|
||||
|
||||
|
||||
- les sommes (constructeurs)
|
||||
- les types sommes (constructeurs) : modélisation de domaines finis
|
||||
|
||||
|
||||
.. code-block:: ocaml
|
||||
|
||||
# type couleur = Pique | Coeur | Carreau | Trefle;;
|
||||
# let v = (Pique , Coeur);;
|
||||
val v : couleur * couleur = (Pique , Coeur)
|
||||
# let a = Trefle ;;
|
||||
val a : couleur = Trefle
|
||||
|
||||
|
||||
.. code-block:: ocaml
|
||||
|
||||
|
|
Loading…
Reference in New Issue