• Aucun résultat trouvé

Listes, files et piles

N/A
N/A
Protected

Academic year: 2022

Partager "Listes, files et piles"

Copied!
39
0
0

Texte intégral

(1)

Listes, files et piles

Thèmes abordés

• Introduction à l’analyse de la complexité algorithmique

• TDA Liste

• TDA Liste

– Implémentation sous forme de tableau.

– Opérations élémentaires. Analyse de la complexité.

• TDA Liste chaînée

– Introduction aux structures de données récursives.

– Liste simplement chaînée, opérations et complexité.

– Liste doublement chaînée, opérations et complexité.

A t TDA

• Autres TDA – Files, piles

– Aperçu des arbres et des graphes.

• Quelques algorithmes de tri – Analyse de complexité

(2)

Introduction à la complexité algorithmique

Analyse des temps d’exécution des algorithmes

• Le temps d’exécution d’un algorithme dépend

De l’organisation de traitements dans l’algorithme figé – De l’organisation de traitements dans l’algorithme.

– Des données entrante dans l’algorithme.

– De la qualité du code généré par le compilateur.

– De la rapidité d’exécution du microprocesseur.

• Nécessité de pouvoir prédire le pire temps d’exécution

– Pour pouvoir garantir une réactivité acceptable des applications.

figé

figé figé variable

Analyse et programmation 2 - Listes, files et piles 2

Introduction à la complexité algorithmique

Analyse des temps d’exécution des algorithmes

• On considère un algorithme

Rece ant en entrée ne donnée dépendant d’ n facte r N – Recevant en entrée une donnée dépendant d’un facteur N

• Peut être une valeur utilisée pour un calcul : factorielle(N).

• Peut être la taille d’une donnée : tableau ou liste de taille N.

– Temps d’exécution de cet algorithme: donné par une fonction

• T(N)

• Complexité algorithmique

– On dit que l’algorithme est de complexité O(f(n)) s’il existe On dit que l algorithme est de complexité O(f(n)) s il existe

• Une fonction f(n)

• deux constantes c et n0

– telles que

• Pour tout n > n0, T(n) < c . f(n)

(3)

Analyse des temps d’exécution des programmes – exemples simples

int produit(int a, int b) {

return a * b;

}

O(1)

}

int factorielle(int n) {

int i, resultat;

resultat = 1;

for (i = 2; i <= n; i++)

resultat = produit(resultat, i);

return resultat;

}

O(n)

Analyse et programmation 2 - Listes, files et piles 4

double developpement_limite_exponentielle(doublex, int n) {

double resultat = 0.0;

int i;

for (i = 0; i <= n; i++)

resultat = resultat + pow(x, i) / factorielle(i);

return resultat;

}

O(n2)

TDA Liste

Introduction – Les applications

Liste de fichiers

Liste d’imprimantes

Liste de périphériques

Liste d’utilisateurs

(4)

TDA Liste

Introduction – Les applications

Liste de livres

Analyse et programmation 2 - Listes, files et piles 6

TDA Liste

Introduction – Les applications

• Ce support de cours

Liste de diapositi es – Liste de diapositives

• Chaque diapositive

– Liste de symboles – Liste d’animations

• Un polygone

– Liste de segments

• Une feuille de calcul

– Liste de cellules

• Un document de traitement de texte

– Liste de caractères

(5)

Définition

• Une liste est

Une collection d’éléments de même t pe – Une collection d’éléments de même type.

– Par opposition à un tableau, le nombre d’éléments est variable.

– Les éléments peuvent être

• Des données de type simple : int, double, …

• Des données composées : struct, tableau.

• Illustration

Analyse et programmation 2 - Listes, files et piles 8

Illustration

– Exemples du cours basés sur une liste de réels.

TDA Liste – représentation sous forme de tableau

Les opérations

• Initialiseurs

Initialiser la liste – Initialiser la liste.

• Sélecteurs

– Taille, Accès à un élément, Vide, Pleine.

• Modificateurs

– Ajouter en fin, Insérer, Supprimer, Vider.

• Itérateurs

– Accéder aux éléments en séquence.

(6)

TDA Liste - tableau

Représentation interne sous forme de tableau à taille fixe

• Principe

Utilisation d’ n tablea à taille fi e s rdimensionné – Utilisation d’un tableau à taille fixe, surdimensionné

– Mémorisation du nombre d’éléments effectif dans une variable.

• Déclaration du type de données

#define CAPACITE_LISTE_TABLEAU 100

typedef double ELEMENT;

Rappel – TDA :

Analyse et programmation 2 - Listes, files et piles 10

typedef struct {

int nombre_elements;

ELEMENT elements[CAPACITE_LISTE_TABLEAU];

} LISTE_TABLEAU;

Une application n’accède jamais directement aux champs !

TDA Liste – représentation sous forme de tableau

Les opérations

#define INDICE_INVALIDE -1

void liste_initialiser(LISTE_TABLEAU* liste);

int liste_nombre_elements(LISTE_TABLEAU* liste);

int liste_pleine(LISTE_TABLEAU* liste);

int liste_vide(LISTE_TABLEAU* liste);

ELEMENT liste_element(LISTE_TABLEAU* liste, int indice);

int liste_position_element(LISTE_TABLEAU* liste, ELEMENT e);

// Resultat : indice de l'élément, ou INDICE_INVALIDE en cas d'échec int liste_ajouter(LISTE_TABLEAU* liste, ELEMENT e);

int liste_inserer(LISTE_TABLEAU* liste, int indice, ELEMENT e);

int liste_supprimer(LISTE_TABLEAU* liste, int indice);

(7)

Initialisation

• But

Préparer la liste à rece oir des éléments – Préparer la liste à recevoir des éléments.

– Initialement, la liste sera donc vide.

• Implémentation

void liste_initialiser(LISTE_TABLEAU* liste) {

liste->nombre_elements = 0;

}

Analyse et programmation 2 - Listes, files et piles 12

• Complexité O(1)

TDA Liste - tableau

Accès au nombre d’éléments

int liste_nombre_elements(LISTE_TABLEAU* liste) {

return liste->nombre_elements;

}

int liste_pleine(LISTE_TABLEAU* liste) {

return liste_nombre_elements(liste) ==

CAPACITE_LISTE_TABLEAU;

} }

int liste_vide(LISTE_TABLEAU* liste) {

return liste_nombre_elements(liste) == 0;

}

Réutilisation d’une opération du TDA

(8)

TDA Liste - tableau

Accès à un élément par position

ELEMENT liste_element(LISTE_TABLEAU* liste, int indice) {

if (indice >= 0 && indice < liste->nombre_elements) return liste->elements[indice];

else {

printf("Erreur d'indice\n");

return 0;

}

} Contrôles de validité du TDA

Analyse et programmation 2 - Listes, files et piles 14

}

TDA Liste - tableau

Recherche de la position d’un élément

int liste_position_element(LISTE_TABLEAU* liste, ELEMENT e) {

int i int i;

int indice;

indice = INDICE_INVALIDE;

for (i = 0; i < liste->nombre_elements; i++) if (liste->elements[i] == e)

{

indice = i;

break;

} }

return indice;

}

Complexité ?

(9)

Ajout d’un élément à la fin

int liste_ajouter(LISTE_TABLEAU* liste, ELEMENT e) {

{

int indice;

if (!liste_pleine(liste)) {

indice = liste->nombre_elements;

liste->elements[indice] = e;

liste->nombre_elements++;

}

Contrôle de validité du TDA

Analyse et programmation 2 - Listes, files et piles 16

} else

indice = INDICE_INVALIDE;

return indice;

} Complexité ?

TDA Liste - tableau

Insertion d’un élément à une position donnée

0 1 2 3 4 5 6 7 8 9 10 11 12 13

2.0 1.5 7.3 8.1 4.5 6.3

liste_inserer(liste, 2, 9.9);

2.0 1.5 7.3 8.1 4.5 6.3

0 1 2 3 4 5 6 7 8 9 10 11 12 13

2.0 1.5 7.3 8.1 4.5 6.3

1

6.3

2

4.5

3

8.1

4

7.3

0 1 2 3 4 5 6 7 8 9 10 11 12 13

1èreétape

0 1 2 3 4 5 6 7 8 9 10 11 12 13

2.0 1.5 7.3 8.1 4.5 6.3 6.3 9.9 7.3 8.1 4.5

5 2èmeétape

(10)

TDA Liste - tableau

Insertion d’un élément à une position donnée

int liste_inserer(LISTE_TABLEAU* liste, int indice, ELEMENT e) {

int i;

int i;

int resultat;

if (!liste_pleine(liste))

if (indice >= 0 && indice <= liste->nombre_elements) {

for (i = liste->nombre_elements; i > indice; i--) liste->elements[i] = liste->elements[i - 1];

liste->nombre_elements++;

liste->elements[indice] = e;

Analyse et programmation 2 - Listes, files et piles 18

resultat = indice;

} else

resultat = INDICE_INVALIDE;

else

resultat = INDICE_INVALIDE;

return resultat;

}

Complexité ?

TDA Liste - tableau

Suppression d’un élément à une position donnée

0 1 2 3 4 5 6 7 8 9 10 11 12 13

2.0 1.5 9.9 7.3 8.1 4.5 6.3

liste_supprimer(liste, 1);

2.0 1.5 9.9 7.3 8.1 4.5 6.3

0 1 2 3 4 5 6 7 8 9 10 11 12 13

2.0 1.5 9.9 7.3 8.1 4.5 6.3

5

6.3

4

4.5

3

8.1

2

7.3

1 1èreétape

9.9

2èmeétape 0 1 2 3 4 5 6 7 8 9 10 11 12 13

2.0 9.9 7.3 8.1 4.5 6.3 6.3

(11)

Suppression d’un élément

int liste_supprimer(LISTE_TABLEAU* liste, int indice) {

int i int i;

int resultat;

if (indice >= 0 && indice < liste->nombre_elements) {

for (i = indice + 1; i < liste->nombre_elements; i++) liste->elements[i - 1] = liste->elements[i];

liste->nombre_elements--;

resultat = indice;

}

Analyse et programmation 2 - Listes, files et piles 20

} else

resultat = INDICE_INVALIDE;

return resultat;

}

Complexité ?

TDA Liste - tableau

Suppression de tous les éléments

0 1 2 3 4 5 6 7 8 9 10 11 12 13

2 0 1 5 9 9 7 3 8 1 4 5 6 3 2.0 1.5 9.9 7.3 8.1 4.5 6.3

0 1 2 3 4 5 6 7 8 9 10 11 12 13

void liste_vider(LISTE_TABLEAU* liste) {

liste->nombre_elements = 0;

}

(12)

TDA Liste - tableau

Parcours de la liste en avant / en arrière

• Le parcours est facile à implémenter et efficace.

• Exemple

• Exemple

void afficher_liste(LISTE_TABLEAU * liste) {

int i, nombre_elements;

nombre_elements = liste_nombre_elements(liste);

printf("{");

for (i = 0; i < nombre_elements; i++) {

if (i 0)

Analyse et programmation 2 - Listes, files et piles 22

if (i > 0)

printf(", ");

printf("%lg", liste_element(liste, i));

}

printf("}");

}

TDA Liste - tableau

Analyse

• Avantages

Accès rapide à to t élément – Accès rapide à tout élément.

– Simplicité.

• Inconvénients

– Opérations d’insertion et de suppression lentes :

• Recopie de nombreux éléments.

• Peu efficace pour des listes volumineuses.

– Besoin de sur-dimensionner les tableaux Besoin de sur dimensionner les tableaux

• Occupation mémoire pas optimisée.

– Aucune flexibilité sur le nombre maximum d’éléments

• Lorsque le maximum prévu est atteint, plus de possibilité d’ajouter ne serait ce qu’un seul élément.

(13)

Représentation interne sous forme de tableau dynamique

• Pour pallier aux inconvénients du tableau fixe

Possibilité d’allo er d namiq ement n tablea – Possibilité d’allouer dynamiquement un tableau.

– Réallocation pour suivre la croissance de la liste.

• Levée des problèmes

– De surconsommation de mémoire.

– De manque de flexibilité.

• Maintien des problèmes d’efficacité

é

Analyse et programmation 2 - Listes, files et piles 24

– Opérations d’insertion et de suppression.

TDA Liste - tableau

Mise en œuvre avec un tableau dynamique

• Déclaration de la structure de données

typedef struct typedef struct {

int capacite;

int nombre_elements;

ELEMENT * elements; // tableau alloué dynamiquement } LISTE_TABLEAU;

(14)

TDA Liste – tableau

Mise en œuvre avec un tableau dynamique

• Fonction privée pour l’allocation de la mémoire

static int liste_etablir_capacite(LISTE_TABLEAU* liste, int capacite_desiree) {

const int PAS_INCREMENT_CAPACITE = 10;

int succes;

int capacite;

ELEMENT * nouveau_tableau;

capacite = (1 + (capacite_desiree - 1) / PAS_INCREMENT_CAPACITE) *PAS_INCREMENT_CAPACITE;

if (liste->capacite != capacite) {

if (liste->elements == NULL) {

liste->elements = (ELEMENT *)malloc(sizeof(ELEMENT) * capacite);

succes = liste->elements != NULL;

} else {

nouveau tableau = realloc(liste >elements sizeof(ELEMENT) * capacite);

Analyse et programmation 2 - Listes, files et piles 26

nouveau_tableau = realloc(liste->elements, sizeof(ELEMENT) * capacite);

succes = nouveau_tableau != NULL;

if(succes)

liste->elements = nouveau_tableau;

}

if (succes)

liste->capacite = capacite;

} else

succes = 1;

return succes;

}

TDA Liste - tableau

Mise en œuvre avec un tableau dynamique

• Initialisation

void liste initialiser(LISTE TABLEAU* liste) void liste_initialiser(LISTE_TABLEAU* liste) {

liste->nombre_elements = 0;

liste->capacite = 0;

liste->elements = NULL;

liste_etablir_capacite(liste, 0);

}

(15)

Mise en œuvre avec un tableau dynamique

• Ajout

int liste ajouter(LISTE TABLEAU* liste ELEMENT e) int liste_ajouter(LISTE_TABLEAU* liste, ELEMENT e) {

int indice;

if (liste_etablir_capacite(liste, liste->nombre_elements + 1)) {

indice = liste->nombre_elements;

liste->elements[indice] = e;

liste->nombre_elements++;

}

Analyse et programmation 2 - Listes, files et piles 28

} else

indice = INDICE_INVALIDE;

return indice;

}

TDA Liste - tableau

Conclusions

• L’utilisation d’un TDA pour une liste est judicieux

Le passage d’ ne liste à taille fi e ers ne liste à taille ariable – Le passage d’une liste à taille fixe vers une liste à taille variable se fait sans aucun changement de spécification sur les opérations du TDA.

– Il faudrait cependant ajouter une opération :

• liste_finaliser

• Pour libérer la mémoire allouée.

• Dans la pratique

– Les listes basées sur des tableaux à taille variables sont très largement utilisées : C++, Java, C#.

– En particulier pour mémoriser des variables de petite taille.

– Souvent le cas en programmation orientée objet

(16)

Analyse et programmation 2 - Listes, files et piles 30

Variantes des listes : les piles

Introduction

• Rappel du fonctionnement d’une pile

Opérations : empiler dépiler – Opérations : empiler, dépiler – Le dernier entré est le premier sorti

• Last In, First Out : LIFO

(17)

Applications pratiques

• Dans la pratique

– Logiciels de bureautique – Logiciels de bureautique

• La fonction « annuler »

• La première opération annulée est la dernière effectuée

– Navigateur Web

• Fonction « précédent »

• La première page ouverte est la dernière

Analyse et programmation 2 - Listes, files et piles 32

ouverte est la dernière lue.

• Utilisées pour de nombreux algorithmes

– Ex : parcours d’arborescence.

Variantes des listes : les piles

Les opérations

• Initialiseur M difi t

• Modificateurs

– Empiler (PUSH) : ajoute un élément sur la pile.

– Dépiler (POP) : enlève l’élément au sommet de la pile.

• Sélecteurs

– Est vide

– Nombre d’éléments.

é é

– Elément situé au sommet.

(18)

Variantes des listes : les piles

Implémentation basée sur la liste tableau

#ifndef __PILE_H_

#define __PILE_H_

#include "ListeTableauDynamique.h"

typedef struct {

LISTE_TABLEAU liste;

} PILE;

void pile_initialiser(PILE * p);

void pile empiler(PILE * p, ELEMENT e);

Analyse et programmation 2 - Listes, files et piles 34

o d p e_e p e ( p, e);

ELEMENT pile_depiler(PILE * p);

int pile_vide(PILE * p);

int pile_nombre_elements(PILE * p);

ELEMENT pile_sommet(PILE * p);

#endif

Variantes des listes : les piles

Implémentation basée sur la liste tableau

void pile_initialiser(PILE * p) {

liste initialiser(&p >liste) liste_initialiser(&p->liste);

}

int pile_vide(PILE * p) {

return pile_nombre_elements(p) == 0;

}

int pile_nombre_elements(PILE * p) {

{

return liste_nombre_elements(&p->liste);

}

void pile_empiler(PILE * p, ELEMENT e) {

liste_ajouter(&p->liste, e);

(19)

Implémentation basée sur la liste tableau

ELEMENT pile_sommet(PILE * p) {

int indice sommet int indice_sommet;

indice_sommet = liste_nombre_elements(&p->liste) - 1;

if (indice_sommet >= 0)

return liste_element(&p->liste, indice_sommet);

else {

printf("Erreur");

return 0;

} }

Analyse et programmation 2 - Listes, files et piles 36

}

Variantes des listes : les piles

Implémentation basée sur la liste tableau

ELEMENT pile_depiler(PILE * p) {

ELEMENT res ltat ELEMENT resultat;

int indice_sommet;

indice_sommet = liste_nombre_elements(&p->liste) - 1;

resultat = pile_sommet(p);

liste_supprimer(&p->liste, indice_sommet);

return resultat;

}

(20)

Variantes des listes : les piles

Implémentation basée sur la liste tableau - Analyse

• Difficulté de programmation ?

• Efficacité d’exécution ?

– Avec des tableaux dynamiques :

Analyse et programmation 2 - Listes, files et piles 38

Avec des tableaux dynamiques :

• Lenteur lors du redimensionnement, surtout avec les grands tableaux.

– Avec des tableaux fixes

• Capacité limitée de la pile

• Sur-occupation de mémoire.

Variantes des listes : les files

Introduction

• Rappel du fonctionnement d’une pile

Opérations : enfiler défiler – Opérations : enfiler, défiler

– Le premier entré est le premier sorti

• First In, First Out : FIFO

(21)

Applications pratiques

• Ordonnancement du traitement des achats d’un magasin en ligne.

• Gestion des ordres reçus par un système embarqué

• Gestion des ordres reçus par un système embarqué.

• File d’attente d’une imprimante.

Analyse et programmation 2 - Listes, files et piles 40

• Traitement de signal : implémentation d’un retard numérique.

Variantes des listes : les files

Les opérations

• Initialiseur M difi t

• Modificateurs

– Enfiler (PUSH) : ajoute un élément à l’entrée de la file.

– Défiler (POP) : enlève un élément à la sortie de la file.

• Sélecteurs

– Est vide

– Nombre d’éléments.

(22)

Variantes des listes : les files

Implémentation basée sur la liste tableau

#ifndef __FILE_H_

#define __FILE_H_

#include "ListeTableauDynamique.h"

typedef struct {

LISTE_TABLEAU liste;

} FILE_TABLEAU;

void file_initialiser(FILE_TABLEAU * f);

void file enfiler(FILE TABLEAU * f, ELEMENT e);

Analyse et programmation 2 - Listes, files et piles 42

o d e_e e ( _ U , e);

ELEMENT file_defiler(FILE_TABLEAU * f);

int file_vide(FILE_TABLEAU * f);

int file_nombre_elements(FILE_TABLEAU * f);

#endif

Variantes des listes : les files

Implémentation basée sur la liste tableau

void file_initialiser(FILE_TABLEAU * f) {

liste initialiser(&f >liste) liste_initialiser(&f->liste);

}

int file_vide(FILE_TABLEAU * f) {

return file_nombre_elements(f) == 0;

}

int file_nombre_elements(FILE_TABLEAU * f) {

{

return liste_nombre_elements(&f->liste);

}

(23)

Implémentation basée sur la liste tableau

void file_enfiler(FILE_TABLEAU * f, ELEMENT e) {

liste ajo ter(&f >liste e) liste_ajouter(&f->liste, e);

}

ELEMENT file_defiler(FILE_TABLEAU * f) {

ELEMENT resultat;

resultat = liste_element(&f->liste, 0);

liste_supprimer(&f->liste, 0);

return resultat;

Analyse et programmation 2 - Listes, files et piles 44

etu esu tat;

}

Variantes des listes : les files

Implémentation basée sur la liste tableau - Analyse

• Difficulté de programmation ?

• Efficacité d’exécution ?

– Opération défiler :

• Décalage des éléments de la liste.

• Opération très coûteuse lorsque la file devient grande.Opé at o t ès coûteuse lo sque la le dev e t g a de.

– Avec des tableaux dynamiques :

• Lenteur lors du redimensionnement, surtout avec les grands tableaux.

– Avec des tableaux fixes

• Capacité limitée de la pile

• Sur-occupation de mémoire.

(24)

Les listes chaînées

Introduction

• Limitations des listes tableaux

Taille fi e – Taille fixe

– Coût élevé des opérations entrainant un déplacement des éléments.

– Coût proportionnel à la taille de la liste.

– Inapproprié pour de très grandes listes.

• Alternative

– Les listes chaînées

Analyse et programmation 2 - Listes, files et piles 46

Les listes chaînées.

– Autre façon de représenter les listes en mémoire.

Structures de donnée récursives

Introduction – Rappel sur la récursivité

• Formulation récursive d’une fonction

– Une fonction récursive est une fonction qui s’appelle elle-même – Une fonction récursive est une fonction qui s appelle elle-même.

• Exemple : définition récursive de la factorielle

U0= 1 Un= n * Un-1

• Mise en œuvre

long factorielle(long n) {

if (n == 0) return 1;

else

return n * factorielle(n - 1);

}

(25)

Introduction

• Structure de données récursive

Une str ct re de données q i se référence elle même – Une structure de données qui se référence elle-même.

• Exemple : définition récursive d’une liste

– Une listec’est

• Soit vide.

• Soit une valeur, suivie d’une autre liste.

– Ce qui peut s’écrire

Liste ::= {} | { Valeur, Liste }

Analyse et programmation 2 - Listes, files et piles 48

{} | { , }

– Cette définition s’appuie donc récursivement sur elle-même.

• Illustration

{}

{ 0, { 1, { 2, { 3, { 4, {} } } } } }

TDA Pile chaînée

Déclaration du type de données en langage C typedef double ELEMENT;

struct CELLULE_PILE_CHAINEE {

ELEMENT element;

struct CELLULE_PILE_CHAINEE * suivant;

};

typedef struct {

struct CELLULE_PILE_CHAINEE * sommet;

} PILE_CHAINEE;

(26)

TDA Pile chaînée

Représentation en mémoire - fonctionnement

• Empilage de 10, 20, 30

CELLULE element: 30 suivant

CELLULE element: 10 suivant: NULL CELLULE

element: 20 suivant CELLULE

element: 30 suivant

CELLULE element: 10 suivant: NULL CELLULE

element: 20 suivant

Analyse et programmation 2 - Listes, files et piles 50

PILE_CHAINEE sommet: NULL PILE_CHAINEE sommet PILE_CHAINEE sommet

TDA Pile chaînée

Représentation en mémoire – fonctionnement par étape - empilage

CELLULE

• Empilage de 10, 20, 30

PILE_CHAINEE sommet: NULL

CELLULE element: 10 suivant: NULL

PILE_CHAINEE sommet PILE_CHAINEE

Sommet: NULL

PILE_CHAINEE

CELLULE element: 10 suivant: NULL

PILE_CHAINEE

CELLULE element: 20 suivant

PILE_CHAINEE CELLULE element: 30 suivant

CELLULE element: 10 suivant: NULL

PILE_CHAINEE

CELLULE element: 20 suivant

(27)

Représentation en mémoire – fonctionnement par étape - dépilage

• Dépilage de 30, 20, 10

CELLULE element: 30 suivant

CELLULE element: 10 suivant: NULL

PILE_CHAINEE sommet

CELLULE element: 20 suivant

CELLULE element: 30 suivant

CELLULE element: 10 suivant: NULL

PILE_CHAINEE sommet

CELLULE element: 20 suivant

Analyse et programmation 2 - Listes, files et piles 52

CELLULE element: 10 suivant: NULL

PILE_CHAINEE sommet

CELLULE element: 20 suivant

CELLULE element: 10 suivant: NULL

PILE_CHAINEE sommet: NULL

TDA Pile chaînée

Opérations

void pile_initialiser(PILE_CHAINEE * pile);

int pile_vide(PILE_CHAINEE * pile);

int pile nombre element(PILE CHAINEE * pile) int pile_nombre_element(PILE_CHAINEE * pile);

void pile_empiler(PILE_CHAINEE * pile, ELEMENT e);

ELEMENT pile_depiler(PILE_CHAINEE * pile);

(28)

TDA Pile chaînée

Opérations

void pile_initialiser(PILE_CHAINEE * pile) {

pile->sommet = NULL;

}

int pile_vide(PILE_CHAINEE * pile) {

return pile->sommet == NULL;

}

Analyse et programmation 2 - Listes, files et piles 54

TDA Pile chaînée

Opérations

void pile_empiler(PILE_CHAINEE * pile, ELEMENT e) {

t t CELLULE PILE CHAINEE * ll ll l struct CELLULE_PILE_CHAINEE * nouvelle_cellule;

// Allocation d'une nouvelle cellule

nouvelle_cellule = (struct CELLULE_PILE_CHAINEE *) malloc(sizeof(struct CELLULE_PILE_CHAINEE));

// mémoriser la valeur de l'élément empilé nouvelle_cellule->element = e;

// Placer la pile actuelle après la nouvelle cellule nouvelle_cellule->suivant = pile->sommet;

// Le nouvel élément est le nouveau sommet de la pile pile->sommet = nouvelle_cellule;

}

(29)

Opérations

ELEMENT pile_depiler(PILE_CHAINEE * pile) {

struct CELLULE_PILE_CHAINEE * cellule_depilee;

ELEMENT resultat;

if (!pile_vide(pile)) {

// Dépilage du sommet de la pile cellule_depilee = pile->sommet;

// Le nouveau sommet est la suite de la cellule depilee pile->sommet = pile->sommet->suivant;

// La valeur depilee est la valeur de la cellule depilee resultat = cellule_depilee->element;

// Liberation de la memoire

Analyse et programmation 2 - Listes, files et piles 56

// Liberation de la memoire free(cellule_depilee);

} else {

printf("Erreur\n");

resultat = 0;

}

return resultat;

}

TDA Pile chaînée

Opérations

int pile_nombre_element(PILE_CHAINEE * pile) {

{

struct CELLULE_PILE_CHAINEE * courant;

int nombre = 0;

courant = pile->sommet;

while (courant != NULL) {

nombre++;

courant = courant->suivant;

}

return nombre;

}

(30)

TDA Pile chaînée

Analyse

• Avantages

Espace mémoire tilisé en fonction d besoin – Espace mémoire utilisé en fonction du besoin.

– Implémentation efficace, même pour de très grandes piles.

• Inconvénients

– L’allocation et la libération de mémoire sont des opérations assez coûteuses.

– Risque de fragmentation de la mémoire.

– Le temps nécessaire à une allocation est très variable

Analyse et programmation 2 - Listes, files et piles 58

Le temps nécessaire à une allocation est très variable.

• Inapproprié pour des applications critiques en temps.

TDA File chaînée

Principe

• On conserve un pointeur sur le début et sur la fin.

E fil à l fi

• Enfilage à la fin.

• Défilage au début.

(31)

TDA File chaînée

Déclaration du type de données en langage C

typedef double ELEMENT;

struct CELLULE_FILE_CHAINEE {

ELEMENT element;

struct CELLULE_FILE_CHAINEE * suivant;

};

typedef struct

Analyse et programmation 2 - Listes, files et piles 60

typedef struct {

struct CELLULE_FILE_CHAINEE * debut;

struct CELLULE_FILE_CHAINEE * fin;

} FILE_CHAINEE;

TDA File chaînée

Représentation en mémoire – fonctionnement de l’enfilage

• Enfilage 10, 20, 30

CELLULE element: 10 suivant: NULL

CELLULE element: 20 suivant: NULL CELLULE

element: 10 suivant

CELLULE element: 30 suivant: NULL CELLULE

element: 20 suivant CELLULE

element: 10 suivant

CELLULE element: 30 suivant: NULL CELLULE

element: 20 suivant

PILE_CHAINEE debut: NULL

suivant: NULL

FILE_CHAINEE debut

suivant: NULL

suivant suivant suivant: NULL

FILE_CHAINEE debut

suivant suivant suivant: NULL

(32)

TDA File chaînée

Représentation en mémoire – fonctionnement de l’enfilage

• Enfilage de 10, 20, 30

FILE_CHAINEE debut: NULL fin: NULL

CELLULE element: 10 suivant: NULL

FILE_CHAINEE debut fin

Analyse et programmation 2 - Listes, files et piles 62

CELLULE element: 10 suivant: NULL

FILE_CHAINEE debut fin

CELLULE element: 20 suivant: NULL CELLULE

element: 10 suivant

CELLULE element: 30 suivant: NULL CELLULE

element: 20 suivant CELLULE

element: 10 suivant: NULL

FILE_CHAINEE debut fin

CELLULE element: 20 suivant: NULL CELLULE

element: 10 suivant

TDA File chaînée

Représentation en mémoire – fonctionnement du défilage

• Defilage de 10, 20, 30

CELLULE CELLULE

element: 10 suivant: NULL

FILE_CHAINEE debut fin

CELLULE element: 20 suivant: NULL CELLULE

element: 10 suivant

CELLULE element: 30 suivant: NULL CELLULE

element: 20 suivant

FILE_CHAINEE debut fin

CELLULE element: 30 suivant: NULL CELLULE

element: 20 suivant

FILE_CHAINEE debut: NULL

CELLULE element: 30 suivant: NULL

(33)

Opérations

void file_initialiser(FILE_CHAINEE * file);

int file_vide(FILE_CHAINEE * file);

int file nombre element(FILE CHAINEE * file) int file_nombre_element(FILE_CHAINEE * file);

void file_enfiler(FILE_CHAINEE * file, ELEMENT e);

ELEMENT file_defiler(FILE_CHAINEE * file);

Analyse et programmation 2 - Listes, files et piles 64

TDA File chaînée

Opérations

void file_initialiser(FILE_CHAINEE * file) {

file->debut = NULL;

file->fin = NULL;

}

int file_vide(FILE_CHAINEE * file) {

return file->debut == NULL;

}

(34)

TDA File chaînée

Opérations

void file_enfiler(FILE_CHAINEE * file, ELEMENT e) {

t t CELLULE FILE CHAINEE * ll ll l struct CELLULE_FILE_CHAINEE * nouvelle_cellule;

// Allocation d'une nouvelle cellule

nouvelle_cellule = (struct CELLULE_FILE_CHAINEE *) malloc(sizeof(struct CELLULE_FILE_CHAINEE));

// mémoriser la valeur de l'élément empilé nouvelle_cellule->element = e;

nouvelle_cellule->suivant = NULL;

if (file->fin != NULL)

// Placer le nouvel élément à la fin file->fin->suivant = nouvelle_cellule;

else

Analyse et programmation 2 - Listes, files et piles 66

// Premier element, c'est aussi le debut file->debut = nouvelle_cellule;

// La nouvelle cellule est à la fin file->fin = nouvelle_cellule;

}

TDA File chaînée

Opérations

ELEMENT file_defiler(FILE_CHAINEE * file) {

struct CELLULE_FILE_CHAINEE * cellule_defilee;

ELEMENT resultat;

if (!file_vide(file)) {

// Défilage du debut de la file cellule_defilee = file->debut;

// Le nouveau debut est la suite de la cellule defilee file->debut = file->debut->suivant;

// La valeur defilee est la valeur de la cellule defilee resultat = cellule_defilee->element;

// Liberation de la memoire // Liberation de la memoire free(cellule_defilee);

} else {

printf("Erreur\n");

resultat = 0;

}

(35)

Opérations

int file_nombre_element(FILE_CHAINEE * file) {

{

struct CELLULE_FILE_CHAINEE * courant;

int nombre = 0;

courant = file->debut;

while (courant != NULL) {

nombre++;

courant = courant->suivant;

}

return nombre;

Analyse et programmation 2 - Listes, files et piles 68

}

TDA Liste chaînée

Introduction

• La file ressemble fortement à une liste.

P bt i l TDA li t il ffit d’ j t l

• Pour obtenir le TDA liste, il suffit d’y ajouter quelques opérations :

ELEMENT liste_element(LISTE_CHAINEE * liste, int position);

void liste_inserer(LISTE_CHAINEE * liste, int position, ELEMENT e);

void liste_supprimer(LISTE_CHAINEE * liste, int position);

• L’implantation de ces opérations se fait de façon similaire. p p ç

(36)

Structures chaînées

Optimisations

• Compteur d’élément

Il est possible d’intégrer n compte r d’éléments dans la – Il est possible d’intégrer un compteur d’éléments dans la

structure.

– Améliore les performances des opérations nécessitant le nombre d’éléments.

• Recyclage des blocs alloués

– L’allocation et la libération des blocs est coûteuse en temps.

– Il est possible de construire une liste globale des blocs libérés.

Analyse et programmation 2 - Listes, files et piles 70

p g

– Utilisation prioritaire de ces blocs en réserve avant toute nouvelle allocation.

Structures dynamiques et systèmes critiques

Recommandations

• En raison de la fragmentation de la mémoire

L’allocation d namiq e pe t écho er après des millions de s ccès – L’allocation dynamique peut échouer après des millions de succès.

– Les temps d’allocation sont en général peu prévisibles.

• Utilisation des structures dynamiques

– Déconseillée, voire même interdite, pour les systèmes critiques.

– Exemples

• Systèmes vitaux dans le domaine médical

• Automobile

• Automobile

• Spatial

– Dans ces domaines, l’allocation dynamique peut être utilisée seulement pendant les phases d’initialisation du logiciel.

(37)

Listes doublement chaînées

• Intérêt

Simplification des algorithmes nécessitant l’élément précédent – Simplification des algorithmes nécessitant l’élément précédent

• Ex: suppression.

– Parcours efficace dans les deux sens.

CELLULE element: 10 suivant: NULL

CELLULE element: 20 suivant: NULL CELLULE

element: 10 suivant

CELLULE element: 30 suivant: NULL CELLULE

element: 20 suivant

Analyse et programmation 2 - Listes, files et piles 72

suivant: NULL

LISTE_DOUBLE_CHAINEE debut

fin

suivant: NULL suivant

precedent:NULL

suivant: NULL precedent suivant

precedent

Autres structures couramment utilisées

Arbres

• Représentation de hiérarchies.

Une cell le pointe ers 2 o pl sie rs cell les filles – Une cellule pointe vers 2 ou plusieurs cellules filles.

– Une cellule n’est pointée qu’une seule fois.

(38)

Autres structures couramment utilisées

Graphes

• Représentation de structures complexes.

Une cell le pointe ers ne o pl sie rs cell les – Une cellule pointe vers une ou plusieurs cellules.

– Une cellule est pointée par une ou plusieurs cellules.

Analyse et programmation 2 - Listes, files et piles 74

Qu’avons-nous appris ?

• Les TDA Liste, File et Pile.

L’i lé t ti t bl

• L’implémentation par tableau.

• L’implémentation avec les structures de données

récursives.

(39)

Vos questions

Analyse et programmation 2 - Listes, files et piles 76

Références

Documents relatifs

Soit f une fonction continue de signe quelconque sur un intervalle [a; b], alors l’int´egrale de la fonction f entre a et b est ´egale ` a la somme des aires des domaines d´efinis

2) Montrer que toute fonction g continue sur un segment est limite uniforme de fonctions lipschitziennes (on pourra approcher g par des fonctions affines par morceaux).. Montrer que

Un nombre entier naturel non nul n est dit parfait si la somme des diviseurs de n qui sont supérieurs ou égaux à 1 est égale au double de n. Par exemple, 6 est un

Soit f une fonction continue et positive d´ efinie sur l’intervalle [a; b] et x un nombre r´ eel quelconque de

Société spécialisée dans la vente par correspondance de biscuits et chocolats, HORIZON 2000 sou- haitait optimiser la gestion de son stock et de ses préparations de commandes dans

Lebois par ses qualités d'aspect et par la diversité de ses mises en œuvre est en mesure d'établir cette transition entre bâti ancien et édifice nouveau en raison de son

[r]

[r]