Vous êtes sur la page 1sur 61

Cours Complexité des Algorithmes

Structure d données : files,listes

Prof. A. BOUZIDI
File d’attente / patients Files d’attente / pages

• Une file est une structure linéaire permettant de stocker et de restaurer


des données selon un ordre FIFO (First In First Out "Premier Entré
Premier Sorti" ).
• Dans une file:
• Les insertions (enfilement) se font à une extrémité appelé queue de la file.
• Les suppressions (défilement) se font à l’autre extrémité appelé tête de la file.
File F

1 12 37 53 9

Queue Tête

Défiler F 1 12 37 53 9

Enfiler Elem de val 8 F 8


• Type File
• Utilise Elément, Booléen
• Opérations
✓ file_vide : → File
✓ est_vide : File → Booléen
✓ enfiler : File x Elément → File
✓ défiler : File → File
✓ tête : File → Elément
• Pré conditions
• défiler(f) est_défini_ssi est_vide(f) = faux
• tête(p) est_défini_ssi est_vide(f) = faux
• Axiomes
• Soit E : Elément , F: File
• est_vide(file_vide) = Vrai
• est_vide(enfiler(F, E)) = Faux
• Si (est_vide(F) = vrai) alors tête(enfiler(F, E)) = e
• Si (est_vide(F) = faux) alors tête(enfiler(F, E)) = tête(f)
• Si (est_vide(F) = vrai) alors défiler(enfiler(f F, E)) = file_vide
• Si (est_vide(F) = faux) alors défiler(enfiler(F, E)) = enfiler(défiler(F), E))
• File_vide: → File
• Initialisation de la file : création d’une file vide
• Est_vide: File → Booléen
• Tester si la file est vide
• Enfiler : File X Elément → File
• Ajouter un élément à la file
• Défiler : File → File
• Supprimer l’élément entête de la file
• Tête : File → Elément
• Consulter l’élément en tête de la file.
• Représentation contigüe (par tableau)
• Les éléments de la file sont rangés dans un tableau
• Deux entiers représentent respectivement les indices des positions de la tête et
de la queue de la file.

• Représentation chaînée (par pointeurs)


• Les éléments de la file sont chaînées entre eux
• Un pointeur sur le premier élément de la file représente la file et désigne la
tête de la file
• Un pointeur sur le dernier élément désigne la queue de la file
• Une file vide est représentée par le pointeur NULL (en C)
• tête de file : position précédant le premier élément
• queue de file :position du dernier élément

• Initialisation:
• tête ← -1
• queue ← -1

• Inconvénient :
• on ne peut plus ajouter un élément dans la file alors qu’elle n’est pas pleine
typedef int Element ;

typedef struct Cellule{ ?


Element valeur;
struct Cellule * suivant;
} Cellule;

typedef struct File{


struct Cellule * tete; tête queu
struct Cellule * queu;
}File;

File file_vide();
File file_enfiler(File f,Element e);
File file_defiler(File f);
Element file_tete(File f);
Booleen est_videF(File f);
File file_vide(){
f.tete=f.queu=NULL;
return f;
}

Booleen est_videF(File f){


if ((f.queu==NULL) || (f.tete ==NULL))
return true;
else
return false;
}
File file_enfiler(File f,Element e){

Cellule * Ctemp =(Cellule *)malloc(sizeof(Cellule));


Ctemp->valeur=e;
Ctemp->suivant=NULL;
if (est_videF(f)==true)
f.tete= Ctemp;
f.queu=Ctemp;
else{
f.queu.suivant=Ctemp;
f.queu=Ctemp;
}
return f;
}
File file_defiler(File f){
if (est_videF(f)==true)
printf("Erreur :file vide !");
else{
f.tete=f.tete->suivant;
if(f.tete == null)
f.queu = null;
}
return f;
}
Soit une file F d’éléments entiers,

• Implémenter les fonctions/opérations de base de votre file.


• Écrire une procédure qui permet de remplir la file par l’utilisateur.
• Écrire une procédure qui affiche tous les éléments de la file.
• Écrire le programme principale qui demande à l’utilisateur de remplir la
file, et à la fin, il affiche les éléments enregistrés.
Soit une file F d’éléments entier,

• Implémenter les fonctions/opérations de base de votre file.


• Ecrire une fonction qui affiche les nombres des éléments de la file.
• Ecrire une procédure qui affiche tous les éléments de la file.
• Ecrire la fonction max qui affiche la valeur maximal, ainsi que son ordre.
• Ecrire la fonction min qui affiche la valeur minimale, ainsi que son ordre.
• Ecrire la fonction moy qui affiche la valeur moyenne.
Soit une file F et une pile P d’éléments entier,

• Peut on inverser une file par l’utilisation d’une pile?

• Si oui, écrire une procédure permettant d’inverser une file.


Cours Complexité des Algorithmes
Structure d données : file

Prof. A. BOUZIDI
• Généralisation des piles et des files :
• Structure linéaire dans laquelle les éléments peuvent être traités les uns à la suite
des autres
• Ajout ou retrait d’élément n’importe ou dans la liste
• Accès à n’importe quel élément
• Une liste est une suite finie, d’éléments de même type repérés par leur
rang dans la liste.
• Chaque élément de la liste est rangé à une certaine place
• Les éléments de la liste sont ordonnés en fonction de leur place
• La longueur d’une liste est le nombre totale de ses éléments
Type Liste
▪ Utilise Elément, Booléen, Place
Opérations
▪ liste_vide : → Liste
▪ longueur : Liste → Entier
▪ inserer : Liste x Elément → Liste
▪ supprimer : Liste → Liste
▪ kème : Liste x Entier → Elément
▪ accès : Liste x Entier → Place
▪ contenu : Liste x Place → Elément – contenu : Liste x Place → Elément
▪ succ : Liste x Place → Place
Pré conditions
▪ inserer(l,k,e) est_défini_ssi 1 ≤k ≤ longueur(l)+1
▪ supprimer(l,k) est_défini_ssi 1 ≤k ≤ longueur(l)
▪ kème(l,k) est_défini_ssi 1 ≤k ≤ longueur(l)
▪ accès(l,k) est_défini_ssi 1 ≤k ≤ longueur(l)
▪ succ(l,p) est_défini_ssi p≠ accès(l,longueur(l))
• liste_vide : → Liste
• Opération d’initialisation : la liste créée est vide,
• longueur : Liste →Entier
• Retourne le nombre d’éléments dans une liste,
• inserer : Liste x Elément → Liste
• Ajoute un élément à la liste dans une position donnée,
• supprimer : Liste → Liste
• Supprimer un élément dans la liste,
• kème : Liste x Entier → Elément
• Fournit l’élément de rang donné dans une liste, Fournit l’élément de rang donné dans une liste,
• accès : Liste x Entier → Place
• Connaître la place de rang donné,
• contenu : Liste x Place → Elément
• Connaitre l’élément d’une place donnée,
• succ : Liste x Place → Place
• Passer d’une place à la place suivante.
• Concatener: Liste × Liste → Liste
• Accroce une deuxième liste en entré à la fin de la première.

• est_exist : Liste × Element → Booléen


• Tester si un élément exist dans la liste
• Représentation contigüe (par tableau)
• Les éléments sont rangés les uns côté des autres dans un tableau
• La kème case du tableau contient le kème élément de la liste.
• Le rang est égale à la place : ce sont des entiers
// taille maximale Liste
#define MAX_LISTE 10

//type des éléments


typedef int Element;
//type place
typedef int Place;

typedef struct {
Element tab[MAX_FILE];
int taille;
} Liste ;
/* fichier "Tliste.h " */
// définition du type liste complémentaire par tableau
#define MAX_LISTE 100 /* taille maximale de la liste */
typedef int Element /* les éléments sont des entiers */
typedef int Place /* place = rang (est un entier) */
typedef struct {
Element tab[MAX_LISTE] ;/*éléments de la liste */
int taille ;
} Liste;
// Déclaration des fonctions gérant la liste
Liste liste_vide()
int longueur(Liste l);
Liste inserer(Liste l,int i, Element e);
Liste supprimer(Liste l, int i);
Element keme (Liste l, int k);
Place acces(Liste l, int i);
Element contenu(Liste l, Place i);
Place succ (Liste l, Place i);
• Représentation contigüe (par tableau)
• Les éléments sont rangés les uns côté des autres dans un tableau
• La kème case du tableau contient le kème élément de la liste.
• Le rang est égale à la place : ce sont des entiers
• Représentation chaînée (par pointeurs)
• Les éléments ne sont pas rangés les uns à côté des autres.
• La place d’un élément est l’adresse d’une structure qui contient l’élément, ainsi que la place de
l’élément suivant.
• Utilisation de pointeurs pour chaîner entre eux les éléments successifs
• En langage C la liste est représentée par un pointeur sur une structure
• La structure contient une élément de la liste et un pointeur sur l’élément suivant.
• La liste vide est représentée par une constante prédéfinie vide (NULL en C/C++)
//type des éléments
typedef int Element;
//type place
typedef struct cellule* Place;
//type cellule
typedef struct {
Element valeur;
Struct cellule *suivant;
} Cellule ;
//type Liste
typedef struct Liste{
Cellule *premier;
};
typedef int Element;
typedef struct Cellule{
Element valeur;
Struct cellule *suivant;
} Cellule ;
typedef struct cellule* Place;
//type Liste
typedef Cellule* Liste;

Liste liste_vide()
int longueur(Liste l);
Liste inserer(Liste l, Element e);
Liste inserer(Liste l,int i, Element e);
Liste supprimer(Liste l, int i);
Element keme (Liste l, int k);
Place acces(Liste l, int i);
Element contenu(Liste l, Place i);
Place succ (Liste l, Place i);
Liste liste_vide() {
return NULL;
}
int longueur(Liste l) {
int taille=0; Liste p=l;
while(p) {
taille++; p = p->suivant;}
return taille;
}

Liste inserer(Liste L, Element e) {


Liste nvelem =(Liste)malloc(sizeof(Cellule));
nvelem ->valeur=e;
nvelem ->suivant = L;
L = nvelem ;
return L;
}
//inserer une element e dans la position i
Liste inserer(Liste L, int i, Element e) {
if (i<0 || i>longueur(L)){
printf(" Erreur : rang non valide !\n");
exit(-1); }
Cellule* nv =(Cellule*)malloc(sizeof(cellule));
nv ->valeur=e;
nv ->suivant =NULL;
if (i==0){
nv->suivant =L;
L=nv; }
else {
List temp = L;
for (int j=0; j<i-1; j++)
temp = temp ->suivant;
nv->suivant = temp ->suivant;
temp -> suivant =nv;
}
return L;
}
Place acces(Liste L, int k){
int i;
Cellule* p;
If (k<0 || k>=longueur(l) { printf("Erreur : rang invalide !\n"); exit(-1); }
If (k==0) return L;
else {
p=L;
for (i=0; i<k; i++)
p= p->suivant;
return p;
}
}
Element contenu(Liste l, Place i){Element contenu(Liste l, Place i){
If (longueur(l) ==0) { printf(" Erreur : liste vide !\n ");
exit(-1); }
Return p->valeur; }

Place succ (Liste l, Place p){


if (p->suivant == NULL) {
printf("Erreur : suivant dernière place !\n");
exit(-1); }
return p->suivant; }
Liste inserer(Liste L,int i, Element e){
if (i<0 || i>longueur(L))
{ printf("Erreur : rang non valide !\n"); exit(-1); }
Liste cl =(Liste)malloc(sizeof(Cellule));
cl->valeur=e; cl>suivant=NULL;
if (i==0) { cl->suivant =L; L=cl; }
else {
int j; Liste p=L;
for (j=0; j<i-1;j++) p=p->suivant;
cl->suivant = p->suivant;
p->suivant = cl;
return L;
}
Liste supprimer(Liste L, int i){
int j;
Liste p;
if (i<0 || i>= longueur(L)) {
printf("Erreur : rang non valide !\n"); exit(-1); }
if (i == 0) {
p=L; L=L->suivant; }
else {
place q;
q=acces(l, i-1); p= succ(l,q);
q->suivant = p->suivant; }
free(p);
return L; }
• Liste avec tête fictive
• Mettre en tête de liste une zone qui ne contient pas de valeur et reste toujours en tête
• Liste chaînée circulaire
• Le suivant du dernier élément de la liste est le premier élément
• Liste doublement chaînée
• Utiliser un double chaînage; chaque place repérant à la fois la place qui la précède et
celle qui la suit
• Liste doublement chaînée circulaire
• Comme liste doublement chaînée et en plus le suivant du dernier élément de la liste
est le premier élément
• Liste triée
• L’ordre des enregistrements dans la liste respecte l’ordre sur les clés
• Soit n le nombre d’éléments d’une liste
Ecrire un programme en langage C qui contient les fonctions suivantes :
• Crée une liste simplement chainée d’employés caractérisés par leur
code, nom, prénom et salaire (la fin de saisie nom égale à FIN).
• Recherche un employé donné selon son code.
• Supprime un employé donné (s’il existe), sachant son code.
• Affiche le nom des employés qui ont un salaire supérieur à la
moyenne.
• Vérifie si la liste est triée (salaire).
• Trie la liste selon l’ordre croissant des salaires.
typedef struct empElement {
int code;
char *nom;
char *prenom;
float sal;
struct empElement *suivant;
}emp ;
typedef struct empElement *liste;
liste ajouter(liste l);
liste rechercher(liste l,int code);
liste supprimer(liste l, int code);
void afficher(liste l);
void afficheliste(liste l);
int verifier(liste l);
liste tri(liste l);
liste inserer (liste l,emp e)
{
liste p = (liste)malloc(sizeof(emp));
p->code = e.code;
p->nom=(char*)malloc(25*sizeof(char));
p->prenom=(char*)malloc(25*sizeof(char));
strcpy(p->nom,e.nom);
strcpy(p->prenom,e.prenom);
p->sal = e.sal;
p->suivant = NULL;
if( l == NULL)
l = p;
else
{
p->suivant = l;
l=p;
}
return l;
}
liste ajouter(liste l)
{
emp e;
do
{
printf("entrer le code de l'employee \n");
scanf("%d",&e.code);
e.nom=(char*)malloc(25*sizeof(char));
printf("entrer le nom de l'employee \n");
scanf("%s",e.nom);
if(strcmp(e.nom,"FIN")!=0)
{
e.prenom=(char*)malloc(25*sizeof(char));
printf("entrer le prenom de l'employee \n ");
scanf("%s",e.prenom);
printf("entrer le salaire de l'employee \n");
scanf("%f",&e.sal);
l=inserer(l,e);
}
}while(strcmp(e.nom,"FIN")!=0);
return l;
}
liste rechercher(liste l,int code)
{
liste p;
p=l;
while((p!=NULL) && (p->code!=code )){
p=p->suivant;
}
return p;
}
liste supprimer(liste l, int code){
liste q, p;
if(l==NULL){
printf("erreur: liste est vide");
exit(-1);}
p=l;
if(p->code==code){
l=l->suivant;
free(p);
return l;}
q=p->suivant;
while (q!=NULL&& q->code!=code){
q=q->suivant;
p=p->suivant;
}
if(q!=NULL){
p->suivant=q->suivant;
free(q);}
return l;}
float moyenne(liste l)
{
liste p;
p=l;
float s=0;
int n=0;
while(p!=NULL){
s+=p->sal;
n++;
p=p->suivant;
}
if(n!=0)
return s/(float)n;
}
void afficher(liste l)
{
float m=moyenne(l);
liste p=l;
while(p)
{
if(p->sal>=m)
{
printf("code=%d\n",p->code);
printf("nom = %s\n",p->nom);
printf("prenom = %s\n",p->prenom);
printf("salaire=%f\n",p->sal);
}
p=p->suivant;
}
}
void afficheliste(liste l)
{
liste p=l;
while(p)
{
printf("code=%d\n",p->code);
printf("nom = %s\n",p->nom);
printf("prenom = %s\n",p->prenom);
printf("salaire=%f\n",p->sal);
p=p->suivant;
}
}
int verifier(liste l){
liste p = l;
if(p==NULL) return 1;
if(p->suivant == NULL) return 1;
while(p->suivant != NULL){
if(p->sal>p->suivant->sal)
return 0;
p = p->suivant;
}
return 1;
}
liste tri(liste l)
{liste p;
int ech;
do{
ech=0; printf("%d ",ech);
for(p=l;p->suivant;p=p->suivant)
{
if(p->sal >p->suivant->sal)
{ech=1;
liste q=(emp*)malloc(sizeof(emp));
q->code=p->code;
q->nom=(char*)malloc(20*sizeof(char));
strcpy(q->nom,p->nom);
q->prenom=(char*)malloc(30*sizeof(char));
strcpy(q->prenom,p->prenom);
q->sal=p->sal;
p->code=p->suivant->code;
strcpy(p->nom,p->suivant->nom);
strcpy(p->prenom,p->suivant->prenom);
p->sal=p->suivant->sal;
p->suivant->code=q->code;
strcpy(p->suivant->nom,q->nom);
strcpy(p->suivant->prenom,q->prenom);
p->suivant->sal=q->sal;
}
}
}while(ech!=0);
return l;
}
void menu(liste l){
int choix;
int code;
emp e;
do{
printf("*************MENU*****************\n");
printf("1:saisir une liste d'employer\n");
printf("2: rechercher un employer selon son code\n");
printf("3: supprimer un employer \n");
printf("4: afficher les employes dont le salaire est superieur a la

moyenne \n");

printf("5: afficher la liste des employes \n");


printf("6: verifie si la liste est trier \n");
printf("7:trier la liste\n");
printf("8: quitter \n" );
printf(" saisir votre choix \n");
scanf("%d",&choix);
switch(choix){
case 1 : l=ajouter(l); break;
case 2 : printf("donner le code de l'employé à rechercher:");
scanf ("%d", &code);
liste p;
p=rechercher(l,code);
if(p==NULL){printf("employé inexistant \n");
}
else {
printf("nom=%s", p->nom);
printf("prenom=%s", p->prenom);
printf("salaire=%f", p->sal);
}break;
case 3: printf("donner le code de l'employé à supprimer:");
scanf ("%d", &code);
l=supprimer(l,code);
break;
case 4:if(l==NULL)
printf("liste vide \n");
else
afficher(l); break;
case 5:if(l==NULL) printf("liste vide \n");
else
afficheliste(l);
break;
case 6: if(verifier(l))
printf("liste triee\n");
else
printf("liste non triee\n");
break;
case 7: if (l) { l=tri(l);
printf("tri effectu\202\n");}
break;
}
}while(choix!=8); }
int main(int argc, char *argv[]) {
liste l=malloc(sizeof(emp));
l=NULL;
menu(l);
system("pause");
return 0;
}
la différence entre les liste simplement chaînée et liste doublement chaînée est que
les maillons d'une liste doublement chaînée possèdent un pointeur sur l'élément qui les
précèdent :

Pointeur sur l’élément précédant Pointeur sur le maillon suivant


Données
• Pour obtenir la structure de base d'une liste doublement chaînée, il suffit
d'ajouter un pointeur sur l'élément précédent dans la structure simple

typedef struct cellule


{
int donnees;
struct noeud *precedent;
struct noeud *suivant;
} cellule;
typedef cellule *liste;
liste

10 15,5 8,75

14,5
Null

Les listes chaînées bidirectionnelles sont utilisées dans le cas où on


a besoin d’établir des retour en arrière.
Créer les types nécessaires pour la mise en œuvre d'une liste
chaînée bidirectionnelle d’entiers. On prévoit trois fonctions : la
première pour ajouter une valeur en tête de liste, la deuxième pour
afficher la liste à l'écran, et la troisième pour vider la liste et libérer
l'espace mémoire.
typedef int Element;
typedef struct cellule2c {
Element valeur;
struct cellule2c *suivant;
struct cellule2c *precedant;
}cellule2c;

typedef cellule2c *liste2c;

liste2c liste2c_vide();
int liste2c_est_vide(liste2c l);
liste2c ajouter(liste2c l,Element e);
liste2c vider (liste2c l);
liste2c liste2c_vide() {
return NULL;
}
int liste2c_est_vide(liste2c l) {
if(l==NULL)
return 1;
return 0;
}
liste2c ajouter(liste2c l,Element e) {
liste2c p=(liste2c)malloc(sizeof(cellule2c));
p->valeur=e; p->suivant=NULL;
p->precedant=NULL;
if(l==NULL){
p->precedant=l;
l=p; return l;
}
l->precedant=p;
p->suivant=l;
l=p;
p->precedant=l;
return l;
}
liste2c vider(liste2c l) {
if(l==NULL)
printf("erreur liste vide \n");
liste2c p;
while(l!=NULL) {
p=l;
l=l->suivant;
free(p);
}
return l; }
void afficher(liste2c l) {
if(l==NULL){
printf("erreur liste vide \n");
}
else {
liste2c p=l;
while(p!= NULL) {
printf("%d \n",p->valeur);
p=p->suivant;
}
}
}
void menu(liste2c l) {
int choix, e;
l=NULL;
do{
printf("Choisissez....\n");
printf("1.Ajouter un élément en tête de liste\n");
printf("2.Vider la liste\n");
printf("3.Afficher les éléments de la liste\n");
printf("4.Quitter \n");
printf("Votre choix: ");
scanf("%d", &choix);
switch(choix) {
case 1: printf("Donnez un entier\n");
scanf("%d", &e);
l=ajouter(l,e);
break;
case 2: l=vider(l); break;
case 3: afficher(l); break;
}
}while(choix!=4); };

Vous aimerez peut-être aussi