Cours d'algorithmique 2 - Intranet 1 8 novembre 2006 Cours dAlgorithmique Listes, piles et files. Arbres. Types de données abstraits. Implantations.
8 novembre 2006Cours d'algorithmique 2 - Intranet2 Trier et chercher Trier et chercher Listes et arbres Listes et arbres Le back-track Le back-track Arbres équilibrés Arbres équilibrés Récursivité et induction sur la structure Récursivité et induction sur la structure Divide and conquer Divide and conquer Minimax Minimax Dérécursion Dérécursion Divers problèmes particuliers Divers problèmes particuliers Logique de Hoare Logique de Hoare Programmation dynamique Programmation dynamique Complexité et calculabilité Complexité et calculabilité Les grandes lignes du cours
8 novembre 2006Cours d'algorithmique 2 - Intranet3 Voici des listes ! Tableau FIN
8 novembre 2006Cours d'algorithmique 2 - Intranet4 Caractérisations dune liste ! Un élément plus un lien vers le suivant. Un élément plus un lien vers le suivant. Séquence ordonnée finie. Séquence ordonnée finie. – Suite ordonnée des mathématiques. Un tableau peut être vu comme une liste, si on limite les accès aléatoires. Un tableau peut être vu comme une liste, si on limite les accès aléatoires. – On lit T[0], puis T[1], etc, par exemple. Une liste est caractérisée par Une liste est caractérisée par – ses propriétés et fonctions daccès – et non sa réalisation.
8 novembre 2006Cours d'algorithmique 2 - Intranet5 Constructeurs et prédicats sur listes Soit LT le type des listes déléments de type T. Le constructeur de la liste vide : cree_vide : void -> LT Le constructeur général : ajout_liste : T x LT -> LT Le prédicat qui distingue les deux cas : est_vide : LT -> BOOL
8 novembre 2006Cours d'algorithmique 2 - Intranet6 Constructeurs et prédicats sur listes Les propriétés vérifiées par ces fonctions : est_vide ( cree_vide () ) = Vrai est_vide ( ajout_liste ( e, l ) ) = Faux La seule liste vide est celle créée par « cree_vide ». La seule liste vide est celle créée par « cree_vide ». Aucune liste obtenue par adjonction dun élément « a » à une liste « l » nest vide. Aucune liste obtenue par adjonction dun élément « a » à une liste « l » nest vide. Salutations de la part de Monsieur de la Palisse ! Salutations de la part de Monsieur de la Palisse !
8 novembre 2006Cours d'algorithmique 2 - Intranet7 Fonctions daccès sur listes La fonction daccès à lélément : tete_liste : LT -> T La fonction daccès à la suite de la liste : queue_liste : LT -> LT Les propriétés vérifiées par ces fonctions : tete_liste ( ajout_liste ( a, l ) ) = a queue_liste ( ajout_liste ( a, l ) ) = l
8 novembre 2006Cours d'algorithmique 2 - Intranet8 Fonctions daccès sur listes Les limitations dapplication de ces fonctions, les appels suivants sont interdits : tete_liste ( cree_vide () ) queue_liste ( cree_vide () ) On parle dune structure Ce qui est vraiment caractéristique dune liste : tete_liste ( ajout_liste ( a, l ) ) = a Last In - First Out (LIFO)
8 novembre 2006Cours d'algorithmique 2 - Intranet9 Types de données abstraits Nous nous sommes donné des noms de types : Nous nous sommes donné des noms de types : – un type de base T, – un type de liste LT sur ce type de base. Nous nous sommes donné des fonctions et leurs propriétés : Nous nous sommes donné des fonctions et leurs propriétés : – cree_vide,..., – est_vide ( cree_vide () ) = Vrai, …. Nous navons pas besoin de devenir plus concrets. Nous navons pas besoin de devenir plus concrets. Cest un type de données abstrait.
8 novembre 2006Cours d'algorithmique 2 - Intranet10 Exemple dimplantation ajout_liste ( 5, ) 21 5 ajout_liste ( 5, cree_vide () ) 5
8 novembre 2006Cours d'algorithmique 2 - Intranet11 Exemple dimplantation tete_liste ( ) queue_liste ( ) 21 5
8 novembre 2006Cours d'algorithmique 2 - Intranet12 Listes et piles Pile ( dassiettes ) stack en anglais ajout_liste = push = empiler tete_liste = top = sommet queue_liste = pop = dépiler LIFO !
8 novembre 2006Cours d'algorithmique 2 - Intranet13 Listes et piles : les différences Les piles sont restreintes aux opérations : Les piles sont restreintes aux opérations : – top, pop et push ( et la détection de la pile vide ), – celles-ci sont réalisées de façon efficace dans le processeur, – par le biais dun tableau !!! Les listes peuvent comporter entre autres : Les listes peuvent comporter entre autres : – en plus de ajout_liste, tete_liste et queue_liste (+ liste vide), – des fonctions comme inserer_liste, supprimer_liste, …, – être doublement chaînées ( cf. TD ) ou circulaires, – et ne sont plus des tableaux ! 2 6 4
8 novembre 2006Cours d'algorithmique 2 - Intranet14 Listes en langage C #include typedef int type_base; typedef struct moi_meme {type_base valeur; struct moi_meme *suivant; } t_maillon, *ptr_liste;
8 novembre 2006Cours d'algorithmique 2 - Intranet15 Listes en langage C ptr_liste cree_vide (void) { return( (ptr_liste)NULL ); } int est_vide (ptr_liste liste) { return( liste == (ptr_liste)NULL ); } type_base tete_liste (ptr_liste liste) {assert( liste != (ptr_liste)NULL ); return( liste->valeur ); } ptr_liste queue_liste (ptr_liste liste) {assert( liste != (ptr_liste)NULL ); return( liste->suivant ); }
8 novembre 2006Cours d'algorithmique 2 - Intranet16 Listes en langage C ptr_liste ajout_liste (type_base elt, ptr_liste liste) {ptr_liste ptr_auxil; ptr_auxil = (ptr_liste)malloc(sizeof(t_maillon)); ptr_auxil->valeur = elt; ptr_auxil->suivant = liste; return( ptr_auxil );} ptr_listeelt liste
8 novembre 2006Cours d'algorithmique 2 - Intranet17 Exporter les types --- fichier adt_liste.c #include typedef int type_base; typedef struct moi_meme {type_base valeur; struct moi_meme *suivant; } t_maillon, *ptr_liste; ptr_liste cree_vide (void); int est_vide (ptr_liste liste); ptr_liste ajout_liste (type_base elt, ptr_liste liste); type_base tete_liste (ptr_liste liste); ptr_liste queue_liste (ptr_liste liste); ptr_liste cree_vide (void) { return( (ptr_liste)NULL ); }... type_liste.h #include type_liste.h adt_liste.h #include adt_liste.h
8 novembre 2006Cours d'algorithmique 2 - Intranet18 Exporter les types --- fichier adt_liste.c #include #include type_liste.h #include adt_liste.h ptr_liste cree_vide (void) { return( (ptr_liste)NULL ); }... Les définitions viennent ici ! Le fichier adt_liste.c
8 novembre 2006Cours d'algorithmique 2 - Intranet19 prog.c qui utilise le type de données liste : #include #include type_liste.h #include adt_liste.h int main (void)... Lutilisateur voit la structure du type de liste. Lutilisateur voit les signatures des fonctions sur les listes. Lutilisateur ne voit pas la réalisation des fonctions, cest-à-dire le contenu de adt_liste.c ! Souvent, cest mieux fait dans dautres langages comme Ada, Modula, C++ et plein dautres.
8 novembre 2006Cours d'algorithmique 2 - Intranet20 Compilation séparée gcc –o executable prog.c gcc –o executable prog.c – On ne peut pas générer lexécutable. – On connaît les signatures des fonctions sur les listes. – Mais, on ne connaît pas leurs réalisations ! gcc –o executable prog.c adt_liste.c gcc –o executable prog.c adt_liste.c – On peut compiler les deux fichiers en même temps. gcc –c prog.c gcc –c prog.c – Nous compilons prog.c pour générer « prog.o ». – Nous navons pas besoin des définitions sur les listes, car nous ne créons pas encore lexécutable. – De même, gcc –c adt_liste.c crée « adt_liste.o ». gcc –o executable prog.o adt_liste.o gcc –o executable prog.o adt_liste.o
8 novembre 2006Cours d'algorithmique 2 - Intranet21 Les fichiers.h Les fichiers «.h » donnent les « types » et/ou les « prototypes ». Les fichiers «.h » donnent les « types » et/ou les « prototypes ». #include #include – file.h est cherché dans les répertoires standard, – mais aussi dans tout répertoire indiqué par - I rép. – Exemple : gcc … - I. - I../local/include … #include file.h #include file.h – file.h est cherché dans le répertoire courant. gcc -Wmissing-prototypes … gcc -Wmissing-prototypes … – Labsence de prototypes est signalée par un avertissement.
8 novembre 2006Cours d'algorithmique 2 - Intranet22 Créer et utiliser les librairies Il existe des librairies statiques, dynamiques et archives. Il existe des librairies statiques, dynamiques et archives. – « ar r libadtl.a adt_liste.o » crée la librairie « libadtl.a » à partir du contenu de « adt_liste.o », – « ar t libadtl.a » affiche le contenu de la librairie. « gcc -o executable -L. prog.c -ladtl » compile prog.c « gcc -o executable -L. prog.c -ladtl » compile prog.c – Le répertoire. est inspecté lors de la recherche des librairies, – on recherche la librairie libadtl.a Lordre des arguments importe : Lordre des arguments importe : – OK : gcc prog-math.c -lm – KO : gcc -lm prog-math.c
8 novembre 2006Cours d'algorithmique 2 - Intranet23 Les files LIFO : listes et piles. LIFO : listes et piles. – Les accès en « ajout », « lecture » et « suppression » se font en tête de liste : InsertionLectureSuppression FIFO : files. FIFO : files. – First In – First Out, cest plus équitable ! – Linsertion se fait à la fin et cest la seule différence. LectureSuppression Insertion Insertion … …
8 novembre 2006Cours d'algorithmique 2 - Intranet24 Les files en langage C ptr_liste ajout_file (type_base elt, ptr_file file) {ptr_file ptr_auxil; ptr_auxil = (ptr_file)malloc(sizeof(t_maillon)); ptr_auxil->valeur = elt; ptr_auxil->suivant = (ptr_file)NULL; if ( file == (ptr_file)NULL ) return( ptr_auxil ); else {ptr_file ptr_local = file; while ( ptr_local->suivant != (ptr_file)NULL ) ptr_local = ptr_local->suivant; ptr_local->suivant = ptr_auxil; return( file ); }}
8 novembre 2006Cours d'algorithmique 2 - Intranet25 Les files Souvent, on maintient deux pointeurs : Souvent, on maintient deux pointeurs : tête tête queue queue Cest plus pratique davoir une structure de synthèse : Cest plus pratique davoir une structure de synthèse :file … …
8 novembre 2006Cours d'algorithmique 2 - Intranet26 Les arbres enracinés racine Il y a un nœud qui est la « racine ». Il y a une orientation de la racine vers les autres.
8 novembre 2006Cours d'algorithmique 2 - Intranet27 Les arbres enracinés racine Les feuilles sont les extrémités de larbre. Du point de vue de larbre, elles sont atomiques (sans successeur). Concernant lapplication, elles comportent souvent des valeurs. 5 13
8 novembre 2006Cours d'algorithmique 2 - Intranet28 Les arbres enracinés racine Il y a des nœuds (internes) qui ont des « fils » en nombre variable. Chaque fils est à son tour un arbre. Concernantlapplication, les nœuds peuventcomporter des valeurs, que lon appelle aussi des étiquettes. x +
8 novembre 2006Cours d'algorithmique 2 - Intranet29 Les arbres enracinés Un arbre est Un arbre est – soit, simplement une feuille : racine racine – soit, un nœud (racine) avec un ou plusieurs fils qui sont des arbres (enracinés) à leur tour : racine racine arbre arbre arbre arbre arbre arbre
8 novembre 2006Cours d'algorithmique 2 - Intranet30 Les arbres enracinés (binaires) comme ADT Création dune feuille : Création dune feuille : – cree_feuille : void -> A – cree_feuille : int -> A pour créer une feuille qui comporte une valeur entière, avec : valeur_feuille : A -> int valeur_feuille : A -> int Création dun nœud binaire : Création dun nœud binaire : – cree_arbre : A x A -> A – cree_arbre : A x int x A -> A pour créer un nœud qui comporte une étiquette entière, avec : etiquette_arbre : A -> int etiquette_arbre : A -> int
8 novembre 2006Cours d'algorithmique 2 - Intranet31 Les arbres enracinés (binaires) comme ADT Distinction entre feuilles et noeuds : Distinction entre feuilles et noeuds : – est_feuille : A -> BOOL est_feuille( cree_feuille() ) = Vrai est_feuille( cree_feuille() ) = Vrai est_feuille( cree_noeud( x, y ) ) = Faux est_feuille( cree_noeud( x, y ) ) = Faux Décomposition dun nœud binaire : Décomposition dun nœud binaire : – fils_gauche : A -> A – fils_droit : A -> A fils_gauche ( cree_arbre ( g, d ) ) = g fils_gauche ( cree_arbre ( g, d ) ) = g fils_droit ( cree_arbre ( g, d ) ) = d fils_droit ( cree_arbre ( g, d ) ) = d
8 novembre 2006Cours d'algorithmique 2 - Intranet32 Les arbres enracinés (binaires) comme ADT arbre_un = cree_arbre ( cree_feuille(5), cree_feuille(7) ); arbre_deux = cree_arbre ( cree_feuille(2), cree_arbre ( arbre_un, cree_feuille(1) ) ); arbre_trois = cree_arbre ( cree_feuille(3), cree_feuille(7) ); arbre = cree_arbre ( arbre_deux, arbre_trois );
8 novembre 2006Cours d'algorithmique 2 - Intranet33 Les arbres en langage C Un pointeur sur un arbre est : Un pointeur sur un arbre est : – soit, un pointeur sur une feuille, – soit, un pointeur sur un nœud. Il faut donc une structure capable de contenir les deux : Il faut donc une structure capable de contenir les deux : – les champs dune feuille, – les champs dun nœud, – un indicateur booléen qui distingue les deux cas de figure. Exemple, (expressions arithmétiques) : Exemple, (expressions arithmétiques) : – toute feuille est un entier, – chaque nœud comporte : un opérateur parmi « + », « * » et « - », un opérateur parmi « + », « * » et « - », deux fils qui sont des sous-expressions. deux fils qui sont des sous-expressions.
8 novembre 2006Cours d'algorithmique 2 - Intranet34 Les arbres en langage C typedef struct moi_meme {int est_feuille; vaudra VRAI {int est_feuille; vaudra VRAI int valeur; aura une valeur int valeur; aura une valeur char etiq; char etiq; struct moi_meme *fg; struct moi_meme *fg; struct moi_meme *fd; struct moi_meme *fd; } t_arbre, *ptr_arbre; Si cest une feuille … Ces champs nont simplement aucun sens dans ce contexte !
8 novembre 2006Cours d'algorithmique 2 - Intranet35 Les arbres en langage C typedef struct moi_meme {int est_feuille; vaudra FAUX {int est_feuille; vaudra FAUX int valeur; int valeur; char etiq; aura une valeur char etiq; aura une valeur struct moi_meme *fg; aura une valeur struct moi_meme *fg; aura une valeur struct moi_meme *fd; aura une valeur struct moi_meme *fd; aura une valeur } t_arbre, *ptr_arbre; Si cest un noeud … Le champ « valeur » na simplement aucun sens dans ce contexte ! En Pascal, ADA et dautres, il existe des structures variables !
8 novembre 2006Cours d'algorithmique 2 - Intranet36 Les arbres en langage C int est_feuille (ptr_arbre arbre) {return(arbre->est_feuille);} ptr_arbre cree_feuille (int val) {ptr_arbre arbre; arbre = (ptr_arbre)malloc(sizeof(t_arbre)); arbre = (ptr_arbre)malloc(sizeof(t_arbre)); arbre->est_feuille = 1; arbre->est_feuille = 1; arbre->valeur = val; arbre->valeur = val; return(arbre); return(arbre);}
8 novembre 2006Cours d'algorithmique 2 - Intranet37 Les arbres en langage C ptr_arbre cree_noeud (ptr_arbre fg, ptr_arbre fd, char symbole) {ptr_arbre arbre; arbre = (ptr_arbre)malloc(sizeof(t_arbre)); arbre = (ptr_arbre)malloc(sizeof(t_arbre)); arbre->est_feuille = 0; arbre->est_feuille = 0; arbre->etiq = symbole; arbre->etiq = symbole; arbre->fg = fg; arbre->fg = fg; arbre->fd = fd; arbre->fd = fd; return(arbre); return(arbre);}
8 novembre 2006Cours d'algorithmique 2 - Intranet38 Les arbres en langage C ptr_arbre fils_gauche (ptr_arbre arbre) {assert( !est_feuille(arbre) ); return(arbre->fg); return(arbre->fg);} ptr_arbre fils_droit (ptr_arbre arbre) {assert( !est_feuille(arbre) ); return(arbre->fd); return(arbre->fd);}
8 novembre 2006Cours d'algorithmique 2 - Intranet39 Listes, arbres et le pointeur NULL Une liste peut être vide ! Une liste peut être vide ! Elle sera représentée par le pointeur NULL ! Elle sera représentée par le pointeur NULL ! La raison profonde est le fait que lopération de base est : La raison profonde est le fait que lopération de base est : – la concaténation, – qui est associative – et possède la liste vide comme élément neutre ! Nous avons les fonctions suivantes : Nous avons les fonctions suivantes : – cree_vide – ajout_liste – est_vide – tete_liste – queue_liste
8 novembre 2006Cours d'algorithmique 2 - Intranet40 Listes, arbres et le pointeur NULL Un arbre nest jamais NULL ! Un arbre nest jamais NULL ! Cest juste le programmeur qui lest ! ! ! Cest juste le programmeur qui lest ! ! ! La raison profonde est le fait que lopération de base est : La raison profonde est le fait que lopération de base est : – la construction darbre, – qui nest pas associative – et la question de lélément neutre ne se pose même pas ! Arbre ( A, Arbre ( B, C ) ) = Arbre ( Arbre ( A, B ), C ) / A BC C AB
8 novembre 2006Cours d'algorithmique 2 - Intranet41 Listes, arbres et le pointeur NULL Un arbre nest jamais NULL ! Un arbre nest jamais NULL ! Cest juste le programmeur qui lest ! ! ! Cest juste le programmeur qui lest ! ! ! La raison profonde est le fait que lopération de base est : La raison profonde est le fait que lopération de base est : – la construction darbre, – qui nest pas associative – et la question de lélément neutre ne se pose même pas ! Nous avons les fonctions suivantes : Nous avons les fonctions suivantes : – cree_feuille – cree_noeud – est_feuille – fils_gauche – fils_droit
8 novembre 2006Cours d'algorithmique 2 - Intranet42 Listes, arbres et le pointeur NULL Je peux éventuellement écrire ceci : Je peux éventuellement écrire ceci : typedef struct moi_meme { struct moi_meme fg, fd ; }... { struct moi_meme fg, fd ; }... ptr_arbre cree_feuille (int valeur) { ptr_arbre arbre; { ptr_arbre arbre; arbre = (ptr_arbre)malloc(sizeof(t_arbre)); arbre = (ptr_arbre)malloc(sizeof(t_arbre)); arbre->fg = NULL ; arbre->fg = NULL ; arbre->fd = (int *) valeur ; arbre->fd = (int *) valeur ; return ( arbre ) ; return ( arbre ) ; } Nous utilisons le champ fg pour indiquer que larbre est une feuille,... et le fils droit pour mémoriser sa valeur !