linf 1251 r cursion sur les listes
Download
Skip this Video
Download Presentation
LINF 1251: Récursion sur les Listes

Loading in 2 Seconds...

play fullscreen
1 / 56

LINF 1251: Récursion sur les Listes - PowerPoint PPT Presentation


  • 82 Views
  • Uploaded on

LINF 1251: Récursion sur les Listes. Peter Van Roy Département d’Ingénierie Informatique, UCL [email protected] Ce qu’on va voir aujourd’hui. Résumé du dernier cours Les listes Récursion sur les listes Pattern matching Développement descendant Complexité en temps.

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about ' LINF 1251: Récursion sur les Listes' - mingan


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
linf 1251 r cursion sur les listes

LINF 1251:Récursion sur les Listes

Peter Van Roy

Département d’Ingénierie Informatique, UCL

[email protected]

P. Van Roy, LINF1251

ce qu on va voir aujourd hui
Ce qu’on va voir aujourd’hui
  • Résumé du dernier cours
  • Les listes
  • Récursion sur les listes
  • Pattern matching
  • Développement descendant
  • Complexité en temps

P. Van Roy, LINF1251

r sum du dernier cours

Résumédu dernier cours

P. Van Roy, LINF1251

principes
Principes
  • Une fonction récursive est comme une boucle dans un langage impératif
    • Attention: si vous avez deux boucles imbriquées, vous avez besoin de deux fonctions récursives!
  • Si l’appel récursif est le dernier appel, alors la fonction récursive est exactement comme une boucle
    • Espace mémoire constante, temps proportionnel au nombre d’itérations
  • La programmation avec accumulateurs est recommandée
    • Pour assurer que l’appel récursif soit le dernier appel
    • On peut utiliser un invariant pour dériver un accumulateur
    • Comment trouver un bon invariant?

P. Van Roy, LINF1251

comment trouver un bon invariant
Comment trouver un bon invariant?
  • Principe des “vases communicants”
    • Une formule en deux parties
    • Une partie “disparaît”; l’autre “accumule” le résultat
  • Exemple: calcul efficace des nombres de Fibonacci
    • Définition: F0=0, F1=1, Fn=Fn-1+Fn-2
    • Invariant: le triplet (n-i,Fi-1,Fi)
      • “Invariant” parce que les trois parties du triplet doivent toujours être dans cette relation
    • Un pas de l’exécution: (k,a,b) devient (k-1,b,a+b)
    • Valeur initiale: (n-1,0,1)

P. Van Roy, LINF1251

calcul efficace des nombres de fibonacci
Calcul efficace des nombresde Fibonacci
  • Raisonnement sur l’invariant
    • Invariant: le triplet (n-i,Fi-1,Fi)
    • Un pas de l’exécution: (k,a,b) devient (k-1,b,a+b)
    • Valeur initiale: (n-1,0,1)
    • Valeur finale: (0,Fn-1,Fn)
  • Définition de la fonction:fun {Fibo K A B}if K==0 then Belse {Fibo K-1 B A+B} endend
  • Appel initial: {Fibo N-1 0 1}

P. Van Roy, LINF1251

environnement contextuel d une proc dure 1
Environnement contextueld’une procédure (1)
  • Quand on définit une procédure, on fait deux choses
    • Déclaration de l’identificateur
    • Création de la procédure en mémoire: il y a deux parties, le code de la procédure et son environnement contextuel
  • Une procédure se souvient de l’endroit de sa naissance (son “environnement contextuel”)
  • Quel est l’environnement contextuel de cette procédure?declarefun {Iterate Si}if {IsDone Si} then Sielse {Iterate {Transform Si}} endend

P. Van Roy, LINF1251

environnement contextuel d une proc dure 2
Environnement contextueld’une procédure (2)
  • Pour bien distinguer la déclaration de l’identificateur et la création de la procédure en mémoire, on peut écrire:declareIterate = fun {$ Si}if {IsDone Si} then Sielse {Iterate {Transform Si}} endend
  • La syntaxe fun {$ Si} … end représente une fonction en mémoire (sans identificateur: c’est une fonction anonyme)
    • Le “$” prend la place de l’identificateur
  • L’environnement contextuel contient donc{IsDone, Iterate, Transform}

P. Van Roy, LINF1251

les listes

Les listes

P. Van Roy, LINF1251

pourquoi les listes
Pourquoi les listes?
  • Dans le dernier cours, on a vu la récursion sur les entiers
    • Mais un entier est assez limité
    • On voudrait faire des calculs avec des structures plus complexes et avec beaucoup d’entiers en même temps!
  • La liste
    • Une collection ordonnée d’éléments (une séquence)
    • Une des premières structures utilisées dans les langages symboliques (Lisp, dans les années 50)
    • La plus utile des structures composées

P. Van Roy, LINF1251

d finition intuitive
Définition intuitive
  • Une liste est
    • la liste vide, ou
    • une paire (un cons) avec une tête et une queue
      • La tête est le premier élément
      • La queue est une liste (les éléments restants)

P. Van Roy, LINF1251

la syntaxe d une liste
La syntaxe d’une liste
  • Avec la notation EBNF:<List T> ::= nil | T ‘|’ <List T>
  • <List T> représente une liste d’éléments de type T et T représente un élément de type T
  • Attention à la différence entre | et ‘|’

P. Van Roy, LINF1251

notation pour les types
Notation pour les types
  • <Int> représente un entier; plus précisément l’ensemble de tous les entiers
  • <List <Int>> représente l’ensemble de toutes les listes d’entiers
  • T représente l’ensemble de tous les éléments de type T; nous disons que T est une variable de type
    • Ne pas confondre avec une variable en mémoire!

P. Van Roy, LINF1251

syntaxe pour les listes 1
Syntaxe pour les listes (1)
  • Liste vide: nil
  • Liste non-vide: H|T
    • L’opérateur infixe ‘|’
  • nil, 5|nil, 5|6|nil, 5|6|7|nil
  • nil, 5|nil, 5|(6|nil), 5|(6|(7|nil))

‘|’

5

‘|’

6

‘|’

7

nil

P. Van Roy, LINF1251

syntaxe pour les listes 2
Syntaxe pour les listes (2)
  • Il existe un sucre syntaxique plus court
    • Sucre syntaxique = raccourci de notation qui n’a aucun effet sur l’exécution
  • nil, [5], [5 6], [5 6 7]
  • Attention: dans la mémoire de l’ordinateur, [5 6 7] et 5|6|7|nil sont identiques!

‘|’

5

‘|’

6

‘|’

7

nil

P. Van Roy, LINF1251

la syntaxe compl te une liste est un tuple
La syntaxe complète:une liste est un tuple
  • Une liste est un cas particulier d’un tuple
  • Syntaxe préfixe (l’opérateur ‘|’ devant)
    • nil‘|’(5 nil)‘|’(5 ‘|’(6 nil))‘|’(5 ‘|’(6 ‘|’(7 nil)))
  • Syntaxe complète
    • nil,‘|’(1:5 2:nil)‘|’(1:5 2:’|’(1:6 2:nil))‘|’(1:5 2:’|’(1:6 2:’|’(1:7 2:nil)))

P. Van Roy, LINF1251

la construction d une liste
La construction d’une liste

declare

X1=5|X2

X2=6|X3

X3=7|nil

‘|’

X1

5

‘|’

X2

6

‘|’

7

nil

X3

P. Van Roy, LINF1251

r sum des syntaxes possibles
Résumé des syntaxes possibles
  • On peut écrire

X1=5|6|7|nil

qui est un raccourci pour

X1=5|(6|(7|nil))

qui est un raccourci pour

X1=‘|’(5 ‘|’(6 ‘|’(7 nil)))

  • La plus courte (attention au ‘nil’!)

X1=[5 6 7]

P. Van Roy, LINF1251

calculer avec les listes
Calculer avec les listes
  • Attention: une liste non vide est une paire!
  • Accès à la tête

X.1

  • Accès à la queue

X.2

  • Tester si la liste X est vide:

if X==nil then … else … end

P. Van Roy, LINF1251

la t te et la queue
La tête et la queue
  • On peut définir des fonctions

fun {Head Xs}

Xs.1

end

fun {Tail Xs}

Xs.2

end

P. Van Roy, LINF1251

exemple avec head et tail
Exemple avec Head et Tail
  • {Head [a b c]}

donne a

  • {Tail [a b c]}

donne [b c]

  • {Head {Tail {Tail [a b c]}}}

donne c

  • Dessinez les arbres!

P. Van Roy, LINF1251

r cursion sur les listes

Récursion surles listes

P. Van Roy, LINF1251

exemple de r cursion sur une liste
Exemple derécursion sur une liste
  • On a une liste d’entiers
  • On veut calculer la somme de ces entiers
      • Définir la fonction Sum
  • Définition inductive sur la structure de liste
      • Sum de la liste vide est 0
      • Sum d’une liste non vide L est

{Head L} + {Sum {Tail L}}

P. Van Roy, LINF1251

somme des l ments d une liste m thode na ve
Somme des éléments d’une liste (méthode naïve)

fun {Sum L}

if L==nil then

0

else

{Head L} + {Sum {Tail L}}

end

end

P. Van Roy, LINF1251

somme des l ments d une liste avec accumulateur
Somme des éléments d’une liste (avec accumulateur)

fun {Sum2 L A}

if L==nil then

A

else

{Sum2 {Tail L} A+{Head L}}

end

end

P. Van Roy, LINF1251

transformer le programme pour obtenir l accumulateur
Transformer le programme pour obtenir l’accumulateur
  • Arguments:
    • {Sum L}
    • {Sum2 L A}
  • Appels récursifs
    • {Head L} + {Sum {Tail L} }
    • {Sum2 {Tail L} A+{Head L} }
  • Cette transformation marche parce que l’addition est associative
    • Sum fait (1+(2+(3+4))), Sum2 fait ((((0+1)+2)+3)+4)

P. Van Roy, LINF1251

autre exemple la fonction nth
Autre exemple: la fonction Nth
  • Définir une fonction {Nth L N} qui renvoie la nième élément de L
  • Le type de Nth est: <fun {$ <List T> <Int>}:<T>>
  • Raisonnement:
    • Si N==1 alors le résultat est {Head L}
    • Si N>1 alors le résultat est {Nth {Tail L} N-1}

P. Van Roy, LINF1251

la fonction nth
La fonction Nth
  • Voici la définition complète:fun {Nth L N}if N==1 then {Head L}elseif N>1 then {Nth {Tail L} N-1}endend
  • Qu’est-ce qui se passe si le nième élément n’existe pas?

P. Van Roy, LINF1251

pattern matching

Pattern matching

P. Van Roy, LINF1251

sum avec pattern matching
Sum avec pattern matching

fun {Sum L}

case L

of nil then 0

[] H|T then H+{Sum T}

end

end

P. Van Roy, LINF1251

sum avec pattern matching1
Sum avec pattern matching

fun {Sum L}

case L

of nil then 0

[] H|T then H+{Sum T}

end

end

Une clause

  • “nil” est la forme (pattern) de la clause

P. Van Roy, LINF1251

sum avec pattern matching2
Sum avec pattern matching

fun {Sum L}

case L

of nil then 0

[] H|T then H+{Sum T}

end

end

Une clause

  • “H|T” est la forme (pattern) de la clause

P. Van Roy, LINF1251

pattern matching1
Pattern matching
  • La première clause utilise of, les autres []
  • Les clauses sont essayées dans l’ordre
  • Une clause correspond si sa forme correspond
  • Une forme correspond, si l’étiquette (label) et les arguments correspondent
      • Les identificateurs dans la forme sont alors affectés aux parties correspondentes de la liste
  • La première clause qui correspond est exécutée, pas les autres

P. Van Roy, LINF1251

longueur d une liste
Longueur d’une liste
  • Définition inductive
      • Longueur d’une liste vide est 0
      • Longueur d’une paire est 1 + longueur de la queue

fun {Length Xs}

case Xs

of nil then 0

[] X|Xr then 1+{Length Xr}

end

end

P. Van Roy, LINF1251

longueur d une liste 2
Longueur d’une liste (2)
  • Avec une forme en plus!

fun {Length Xs}

case Xs

of nil then 0

[] X1|X2|Xr then 2+{Length Xr}

[] X|Xr then 1+{Length Xr}

end

end

P. Van Roy, LINF1251

longueur d une liste 3
Longueur d’une liste (3)
  • Quelle forme ne sera jamais choisie?

fun {Length Xs}

case Xs

of nil then 0

[] X|Xr then 1+{Length Xr}

[] X1|X2|Xr then 2+{Length Xr}

end

end

P. Van Roy, LINF1251

pattern matching en g n ral
Pattern matching en général
  • Le pattern matching peut être utilisé pour beaucoup plus que les listes
  • Toute valeur, y compris nombres, atomes, listes, tuples, enregistrements
    • Nous allons voir les tuples dans le prochain cours
  • Les formes peuvent être imbriquées
  • Certains langages connaissent des formes encore plus générales (expressions régulières)

P. Van Roy, LINF1251

calculs sur les listes
Calculs sur les listes
  • Une liste est une liste vide ou une paire avec une tête et une queue
  • Un calcul avec une liste est un calcul récursif
  • Le pattern matching est une bonne manière d’exprimer de tels calculs

P. Van Roy, LINF1251

m thode g n rale pour la r cursion sur les listes
Méthode générale pour la récursion sur les listes
  • Il faut traiter les listes de façon récursive
      • Cas de base: la liste est vide (nil)
      • Cas inductif: la liste est une paire (cons)
  • Une technique puissante et concise
      • Le pattern matching (correspondance des formes)
      • Fait la correspondance entre une liste et une forme (“pattern”) et lie les identificateurs dans la forme

P. Van Roy, LINF1251

d veloppement descendant

Développementdescendant

P. Van Roy, LINF1251

le triangle de pascal 1
Le triangle de Pascal (1)
  • Nous allons définir la fonction {Pascal N}
  • Cette fonction prend un entier N et donne la Nième rangée du triangle de Pascal, représentée comme une liste d’entiers
  • Une définition classique est que {Pascal N} est la liste des coefficients dans l’expansion de (a+b)n

1

1

1

1

2

1

(0)

1

3

3

1

(0)

1

4

6

4

1

P. Van Roy, LINF1251

le triangle de pascal 2
Le triangle de Pascal (2)

1

  • Calculez la fonction {Pascal N}
  • Pour la rangée 1, cela donne [1]
  • Pour la rangée N, déplacez à gauche la rangée N-1 et déplacez à droite la rangée N-1
  • Alignez les deux rangées déplacées et additionnez-les élément par élément pour obtenir la rangée N

1

1

1

2

1

(0)

1

3

3

1

(0)

1

4

6

4

1

Déplacez à droite:

[0 1 3 3 1]

[1 3 3 1 0]

Déplacez à gauche:

P. Van Roy, LINF1251

sch ma de la fonction
Schéma de la fonction

Pascal N

Pascal N-1

Pascal N-1

ShiftLeft

ShiftRight

AddList

P. Van Roy, LINF1251

code de la fonction
Code de la fonction

declare

fun{Pascal N}

ifN==1then[1]

else

{AddList

{ShiftLeft {Pascal N-1}}

{ShiftRight {Pascal N-1}}}

end

end

Pascal N

Pascal N-1

Pascal N-1

ShiftLeft

ShiftRight

AddList

P. Van Roy, LINF1251

fonctions auxiliaires 1
Fonctions auxiliaires (1)

fun {ShiftLeft L}

case L of H|T then

H|{ShiftLeft T}

else [0]

end

end

fun {ShiftRight L} 0|L end

P. Van Roy, LINF1251

fonctions auxiliaires 2
Fonctions auxiliaires (2)

fun {AddList L1 L2}

case L1 of H1|T1 then

case L2 of H2|T2 then

H1+H2|{AddList T1 T2}

end

else nil end

end

P. Van Roy, LINF1251

une d finition plus courte d addlist
Une définition plus courte d’AddList
  • Un exemple d’une forme (pattern) plus compliquéefun {AddList L1 L2}case L1#L2 of (H1|T1)#(H2|T2) then(H1+H2)|{AddList T1 T2}else nil endend
  • L1#L2 est une paire de deux variables
    • Avec ‘#’ on peut grouper deux variables (un peu comme ‘|’)
  • La forme (H1|T1)#(H2|T2) fait la correspondance avec L1 et L2 en même temps

P. Van Roy, LINF1251

d veloppement descendant top down
Développement descendant (”top-down”)
  • Ce que nous avons fait avec Pascal est un exemple de développement descendant (”top-down”)
  • D’abord, il faut comprendre comment résoudre le problème à la main
  • On résoud le problème en le décomposant en de tâches plus simples
  • La fonction principale (Pascal) est définie en utilisant des fonctions auxiliaires (ShiftLeft, ShiftRight et AddList)
  • On complète la solution en définissant les fonctions auxiliaires

P. Van Roy, LINF1251

complexit en temps

Complexité en temps

P. Van Roy, LINF1251

temps d ex cution
Temps d’exécution
  • Quel est le temps d’exécution de {Pascal N} en fonction de N?
    • Temps = tPascal(N)
  • Ce qui nous intéresse est la forme de la fonction tPascal(N)
    • Si nous achetons un ordinateur plus rapide, le temps diminuera: tPascal(N)/10 par exemple
    • Mais la forme de la fonction ne changera pas!
  • Qu’est-ce qui se passe quand N devient grand?

P. Van Roy, LINF1251

complexit en temps1
Complexité en temps
  • La complexité en temps O(f(n))
    • t(n) est de l’ordre f(n) s’il existe une constante c telle que t(n) ≤ c.f(n)
    • On écrit t(n) = O(f(n))
  • Par exemple, si tShiftLeft(n) est le temps d’exécution de {ShiftLeft L}, on peut dire:
    • tShiftLeft(n) = O(n) avec n=|L|
  • Pour {ShiftRight L} c’est plus simple:
    • tShiftRight(n) = O(1)

P. Van Roy, LINF1251

complexit de pascal n
Complexité de {Pascal N}
  • Quelle est la complexité de {Pascal N}?
    • tPascal(N) = O(2n)
    • Cela grandit très vite quand N augmente
      • Complexité exponentielle: n est dans l’exposant
      • L’histoire de l’inventeur des échecs et le shah
    • Même avec N relativement petit on ne peut pas calculer {Pascal N} dans un temps raisonnable
  • Pourquoi le temps augmente aussi vite?
    • Parce qu’il y a deuxappels récursifs {Pascal N-1}

P. Van Roy, LINF1251

complexit exponentielle
Complexité exponentielle

declare

fun{Pascal N}

ifN==1then[1]

else

{AddList

{ShiftLeft {Pascal N-1} }

{ShiftRight {Pascal N-1} }}

end

end

Pascal N

Pascal N-1

Pascal N-1

ShiftLeft

ShiftRight

AddList

P. Van Roy, LINF1251

fastpascal
FastPascal
  • On peut faire un seulappel si on garde le résultat dans une variable locale Lfun {FastPascal N}if N==1 then [1]else L in L={FastPascal N-1} {AddList {ShiftLeft L} {ShiftRight L}}endend
  • La complexité devient O(n2)
    • Complexité polynomiale: un polynome en n
    • C’est beaucoup plus rapide que O(2n)!

P. Van Roy, LINF1251

r sum

Résumé

P. Van Roy, LINF1251

r sum1
Résumé
  • Les listes
    • Différentes syntaxes possibles, mais toujours la même représentation en mémoire
    • Récursion sur les listes
    • Pattern matching
  • Développement descendant (top-down)
    • Fonctions sur les listes
  • Complexité en temps
    • Complexité exponentielle et polynomiale

P. Van Roy, LINF1251

ad