Vous êtes sur la page 1sur 71

Algorithmique et Programmation Avancée

Plan

Chapitre 1 : Listes chaînées et doublement chainées

Chapitre 2 : Tri des listes chaînées

Chapitre 3 : Les files et les piles

Chapitre 4 : arbres binaires AB, ABR et arbre équilibré


Les listes chaînées

Première année BTP et GM Algorithmique avancée


1. Introduction

Tableau (Insertion dans un tableau plein)


Tableau sous-dimensionné de 4 cases pleines

Tableau sur-dimensionné de 100 cases

95 cases inutilisées

Première année BTP et GM Algorithmique avancée


1. Introduction

Tableau (Insertion dans un tableau Trié)

Première année BTP Algorithmique avancée


1. Introduction

Tableau (Suppression d’un élément)

Suppression de T[4]

La suppression nécessite de décaler les éléments du tableau situé


après l’élément supprimé.

Première année BTP et GM Algorithmique avancée


1. Introduction

Liste chaînée (Insertion/suppression)

-Ajout d’un nœud dynamiquement

-Suppression d’un nœud sans décalage

Première année BTP Algorithmique avancée


1. Introduction

Il existe un grand nombre de structure de données plus performant que les tableaux:
Exemple : listes chaînées, listes doublement chaînées les piles, les files, les arbres binaires...

Ses structures de donnée gèrent un ensemble d’éléments dont le nombre n’est pas fixé,
le nombre des éléments varie au cours de l’exécution du programme, puisqu’on peut y
ajouter et supprimer facilement des éléments en cours de traitement.

Les opérations sur ses structures sont les suivantes :


tester si un ensemble est vide.
ajouter un élément.
supprimer un élément.
rechercher un élément.

Première année BTP Algorithmique avancée


Algorithmique avancée
1. Introduction

Dans une liste chaînée les objets sont stockés de manière ordonnée. L’ordre est déterminé par
un pointeur dans chaque objet contrairement au tableau, pour lequel l’ordre est déterminé par
les indices.

Les listes chaînées peuvent accueillir un nombre infini d’éléments.

Les listes chaînées supportent toutes les opérations (insertion, suppression,


recherche,...).

Chaque élément de la liste est contenu dans une cellule (nœud) composée d’une valeur et d’un
pointeur sur l’élément suivant.

Une liste chaînée est donc une succession de noeuds, dont le dernier porte sur NULL.

Première année BTP Algorithmique avancée


Algorithmique avancée
1. Introduction

La première cellule de la liste est appelée tête (debut) et la dernière cellule est appelée queue
(Fin).
L’accès à la liste chaînée se fait par le pointeur debut sur le premier élément.

Pour atteindre un des éléments de la liste, on est obligé de parcourir la liste


depuis le début.

A partir d’un élément quelconque, on ne peut atteindre que le suivant.

Première année BTP et GM Algorithmique avancée


1. Introduction

Une liste chaînée peut prendre deux formes :


Elle peut être simplement chaînée : chaque cellule est composé de l’information
et d’un seul pointeur.
Ou doublement chaînée : chaque cellule est composé de l’information et de
deux pointeurs (l’un pointe sur l’adresse de la cellule suivante et l’autre sur celle
de la cellule précédente).

liste simplement chaînée

liste doublement chaînée

Première année BTP Algorithmique avancée


2. Listes simplement chaînées

Déclaration

Chaque nœud d’une liste chaînée est une structures constitué : d’un champ de
données et d’un pointeur vers le nœud suivant. La déclaration correspondante est la
suivante:

Code en C
struct element
{
int donnee;
struct element * suivant;
};

typedef struct element Element;

Première année BTP Algorithmique avancée


2. Listes simplement chaînées

Réservation mémoire
struct element{
int donnnee;
struct element *suivant;
};
typedef struct element Element;

Element *chaine;

chaine->donnee =10; /* INVALIDE */


// p ne pointe sur aucune case mémoire valide */

chaine:

chaine = (Element*) malloc(sizeof(Element));


chaine->donnee =10; //Valide

valeur suivant
chaine: 10

Première année BTP Algorithmique avancée


2. Listes simplement chaînées

Element *p;
p = chaine;

p-> suivant = (Element*) malloc(sizeof(Element));

p = p -> suivant;
p -> valeur = 5;

p -> suivant = (Element*) malloc(sizeof(Element));


p = p -> suivant;
p -> valeur = 13;
p -> suivant = NULL;
for (p=chaine; p!=NULL; p=p->suivant)
printf(“%d\n”, p->valeur);

Pour parcourir la liste on doit connaître l’adresse du premier


élément de la liste???
Première année BTP et GM Algorithmique avancée
2. Listes simplement chaînées

Déclaration des infos sur la liste


Pour avoir le contrôle de la liste il est préférable de sauvegarder certains
informations de la liste, par exemple le premier élément, le dernier élément et le
nombre d'éléments. Pour cela une autre structure sera utilisée :

typedef struct Liste


{
Element * debut;
Element * fin;
int taille;
} Liste;

ou
typedef struct Liste{
Eelement * debut;
Eelement *courant;
Eelement *dernier;
}Liste;

Première année BTP Algorithmique avancée


2. Listes simplement chaînées

Initialisation

Pour initialiser notre liste, il suffit d’initialiser les pointeurs debut et fin à NULL
et la taille à 0.
Il est important d’initialiser la liste, sinon le programme provoquera des erreurs
d’exécutions qui seront très difficiles à identifier.

void initListe(Liste * L) {
L->debut = (Element *) malloc ( sizeof(Element));
L->fin = (Element *) malloc ( sizeof(Element));
L->debut = NULL;
L->fin = NULL;
L->taille=0;
}

Première année BTP Algorithmique avancée


2. Listes simplement chaînées

Insertion dans la liste

Pour ajouter un élément dans la liste il y a plusieurs cas:

1. Insertion dans une liste vide


2. Insertion au début de la liste
3. Insertion à la fin de la liste
4. Insertion ailleurs dans la liste

Première année BTP Algorithmique avancée


2. Listes simplement chaînées

Insertion dans une liste vide

int ins_dans_liste_vide (Liste *liste, type donnee);


renvoie -1 en cas d'échec sinon elle renvoie 0.
Étapes :

allocation de la mémoire pour le nouvel élément


remplir le champ de données du nouvel élément
le pointeur suivant du nouvel élément pointera vers NULL

les pointeurs debut et fin pointeront vers le nouvel élément


la taille est mise à jour

Première année BTP Algorithmique avancée


2. Listes simplement chaînées

Insertion dans une liste vide

/* insertion dans une liste vide */


int ins_dans_liste_vide (Liste * liste, char *donnee)
{
Element *nouveau_element;
if ((nouveau_element = (Element *) malloc (sizeof (Element))) == NULL) return -1;

if ((nouveau_element->donnee = (char *) malloc (50 * sizeof (char))) == NULL) return -1;


strcpy (nouveau_element->donnee, donnee);

nouveau_element->suivant = NULL;

liste->debut = nouveau_element;
liste->fin = nouveau_element;
liste->taille++;
return 0;
}
Première année BTP Algorithmique avancée
2. Listes simplement chaînées

Insertion au début de la liste


int ins_debut_liste (Liste *liste, type donnee);
Étapes:
allocation de la mémoire pour le nouvel élément new_elt=malloc(..)
remplir le champ de données du nouvel élément new_elt->donnne=donnee
le pointeur suivant de new_elt pointe vers le 1er élément new_elt->suivant=liste->debut
le pointeur debut pointe vers le nouvel élément liste->debut=new_elt
le pointeur fin ne change pas
la taille est incrémentée liste->taille++

Première année BTP Algorithmique avancée


2. Listes simplement chaînées

Insertion au début de la liste

/* insertion au début de la liste */


int ins_debut_liste (Liste * liste, char *donnee)
{
Element *nouveau_element;
if ((nouveau_element = (Element *) malloc (sizeof (Element))) == NULL)
return -1;
if ((nouveau_element->donnee = (char *) malloc (50 * sizeof (char))) == NULL)
return -1;
strcpy (nouveau_element->donnee, donnee);

nouveau_element->suivant = liste->debut;
liste->debut = nouveau_element;
liste->taille++;
return 0;
}

Première année BTP Algorithmique avancée


2. Listes simplement chaînées

Insertion à la fin de la liste

int ins_fin_liste (Liste *liste, char *donnee);


La fonction renvoie -1 en cas d'échec sinon elle renvoie 0.

Étapes:
allocation de la mémoire pour le nouvel élément
remplir le champ de données du nouvel élément
le pointeur suivant du dernier élément pointe vers le nouvel élément
le pointeur fin pointe vers le nouvel élément
le pointeur debut ne change pas
la taille est incrémentée

Première année BTP Algorithmique avancée


2. Listes simplement chaînées

Insertion à la fin de la liste

/*insertion à la fin de la liste! courant=ptr vers dernier nœud de la liste */


int ins_fin_liste (Liste * liste, char *donnee)
{
Element *nouveau_element;
if ((nouveau_element = (Element *) malloc (sizeof (Element))) == NULL)
return -1;
if ((nouveau_element->donnee = (char *) malloc (50 * sizeof (char))) == NULL)
return -1;
strcpy (nouveau_element->donnee, donnee);

(list->fin) ->suivant = nouveau_element;


nouveau_element->suivant = NULL;
liste->fin = nouveau_element;
liste->taille++;
return 0;
}

Première année BTP Algorithmique avancée


2. Listes simplement chaînées

Insertion ailleurs dans la liste

Prototype de la fonction : int ins_liste (Liste *liste, char *donnee, int pos);
L'insertion s’éffectue après la position pos passée en argument à la fonction.

Étapes:
allocation de la mémoire pour le nouvel élément
remplir le champ de données du nouvel élément
Se déplacer vers la position pos (l'insertion se fera après la pos)
le pointeur suivant du nouvel élément pointe vers l'adresse sur laquelle
pointe le pointeur suivant de pos.
le pointeur suivant de pos pointe vers le nouvel élément
les pointeurs debut et fin ne change pas
la taille est incrémentée d'une unité
Première année BTP Algorithmique avancée
2. Listes simplement chaînées

/* insertion à la position demandée */

int ins_liste (Liste * liste, char *donnee, int pos)


{
if (liste->taille < 2) return -1;
if (pos < 1 || pos >= liste->taille) return -1;
Element *courant;
Element *nouveau_element;
int i;
if ((nouveau_element = (Element *) malloc (sizeof (Element))) == NULL)
return -1;
if ((nouveau_element->donnee = (char *) malloc (50 * sizeof (char))) == NULL)
return -1;
strcpy (nouveau_element->donnee, donnee);
courant = liste->debut;
for (i = 1; i < pos; ++i) courant = courant->suivant;
if (courant->suivant == NULL) return -1;
nouveau_element->suivant = courant->suivant;
courant->suivant = nouveau_element;
liste->taille++;
return 0;
}

Première année BTP Algorithmique avancée


em
2. Listes simplement chaînées

Suppression d'un élément dans la liste

utilisation d'un pointeur supp_elem pour sauvegarder l'adresse d'éléments à supprimer


Le pointeur courant pointe sur le nœud précédent supp_elem
Faire pointer le pointeur suivant de l'élément courant vers l'adresse du pointeur suivant de
l'élément à supprimer
libérer la mémoire occupée par l'élément supprimé
mettre à jour la taille de la liste

Il y a trois façon de supprimer des cellules dans des listes chaînées :

supprimer une cellule en tête de la liste,

supprimer une cellule à la fin de la liste,

supprimer une cellule quelconque dans une liste:


Première année BTP Algorithmique avancée
2. Listes simplement chaînées

Suppression au début de la liste

Prototype de la fonction: int supp_debut (Liste *liste);


Étapes:
le pointeur supp_elem contiendra l'adresse du 1er élément (début)
le pointeur debut pointera vers le 2ème élément
Libérer la mémoire de supp_elem.
la taille de la liste sera décrémentée d'un élément

Première année BTP Algorithmique avancée


2. Listes simplement chaînées

Suppression au début de la liste

/* suppression au début de la liste */


int supp_debut (Liste * liste){
if (liste->taille == 0) return -1;
Element *supp_element;
supp_element = liste->debut;
liste->debut = liste->debut->suivant;
if (liste->taille == 1) liste->fin = NULL;
free (supp_element->donnee);
free (supp_element);
liste->taille--;
return 0;
}

Première année BTP Algorithmique avancée


2. Listes simplement chaînées

Suppression ailleurs dans la liste


Prototype de la fonction: int supp_dans_liste (Liste *liste, int pos);
Suppression de l’élément qui suit la position pos.
Étapes:
le pointeur supp_elem pointera vers courant->suivant (courant pointe sur pos)
lcourant pointera vers courant->suivant->suivant
Si l'élément courant est l'avant dernier élément, le pointeur fin doit être mis à jour
la taille de la liste sera décrémentée d'un élément

Première année BTP Algorithmique avancée


2. Listes simplement chaînées

/* supprimer un element après la position demandée */


int supp_dans_liste (Liste * liste, int pos)
{
if (liste->taille <= 1 || pos < 1 || pos >= liste->taille) return -1;
int i;
Element *courant;
Element *supp_element;
courant = liste->debut;
for (i = 1; i < pos; ++i) courant = courant->suivant;
supp_element = courant->suivant;
courant->suivant = courant->suivant->suivant;
if(courant->suivant == NULL) liste->fin = courant;
free (supp_element->donnee);
free (supp_element);
liste->taille--;
return 0;
}

Première année BTP Algorithmique avancée


2. Listes simplement chaînées

Affichage d’une liste

Affichage d’une liste

/* affichage de la liste */
void affiche (Liste * liste)
{
Element *courant;
courant = liste->debut;
while (courant != NULL){
printf ("%p - %s", courant, courant->donnee);
courant = courant->suivant;
}
}

Première année BTP Algorithmique avancée


2. Listes simplement chaînées

Recherche dans une liste


int recherche(Liste * L, int v){
int i = 1;
int pos = -1;
Element *temp;
temp = (Element * ) malloc(sizeof(Element));
temp = L->debut;
while(pos==-1 && temp !=NULL)
{
if(temp->val == v)
pos = i;
else
{
temp = temp->suivant;
i++;
}
}
return pos;
}

Première année BTP Algorithmique avancée


2. Listes simplement chaînées

L’idée est de parcourir la liste chaînée, et pour


Inversion des listes chaînées
chaque nœud associer à son suivant le nœud
qui le précède au lieu de celui qui le suit.
void inverse(Liste *L) {
Element *temp;
temp = (Element * ) malloc(sizeof(Element));
temp = L->debut; Pour pointer milieu sur la cellule arriere on doit
if (temp!= NULL) { garder un pointeur sur cette dernière.
Element* milieu = temp;
Element* devant = milieu->suivant;
Or du moment où ce changement prend place,
Element* arriere= NULL; la liaison avec le reste de la liste sera détruite,
while (1) { d’où la nécessité de préserver l’adresse de la
milieu->suivant = arriere; cellule devant.
if (devant == NULL) break;
arriere = milieu; Pour assurer le parcours complet de la liste il
milieu = devant; faudra affecter à milieu le pointeur devant qui
devant = devant->suivant; contient l’adresse de la cellule suivante.
}
Finalement il ne faut pas oublier d’affecter
L->debut= milieu; l’adresse de la dernière cellule parcourue au
} pointeur liste car elle représente à cet instant
} la nouvelle entrée de la liste chaînée
Première année BTP Algorithmique avancée
3. TRI

Tri par sélection

Première année BTP Algorithmique avancée


3. TRI

Tri par selection : Tableau


Trouver le minimum du tableau et le positionner a la première case, on le refait pour
le reste du tableau en positionnant le nouveau minimum a la deuxième case etc ...

int i,j,echange;
for(i=0;i<N-1;i++)
for(j=i+1;j<N;j++)
if ( T[j] < T[i] )
{
echange = T[i];
T[i] = T[j];
T[j] = echange;
}

Première année BTP Algorithmique avancée


3. TRI

Démonstration

Première année BTP Algorithmique avancée


3. TRI

Exercice
En s’inspirant du programme précédent qui tri
par sélection les éléments d’un tableau, écrire
une fonction qui tri par sélection la liste chaînée.

struct elem{
double data;
struct elem *suivant;
};
typedef struct elem * liste;

void tri_selection(liste * l)

Première année BTP Algorithmique avancée


3. TRI

Tri par sélection : Liste

void tri_selection(liste l)
{
liste p, q;
double Aux;
if ( l && l>suivant)
for(p=l ; p->suivant; p=p->suivant)
for(q=p->suivant; q; q=q->suivant)
if(p->data> q->data)
{
Aux=p->data;
p->data=q->data;
q->data=Aux;
}
}

Première année BTP Algorithmique avancée


3. TRI

Tester la fonction de tri par sélection en utilisant cette fonction:

liste tableau_vers_liste(double tab[], int n){


int i;
// l : liste retournée (début), d : dernier élément de l, x: nœud à ajouter
liste l = NULL, d = NULL, x;

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


x =(liste) malloc(sizeof(struct elem));
x->suivant = NULL;
x->data = tab[i];
if( d == NULL ) l = d = x;
else{
d->suivant = x;
d = x;
}
}
return l;
}

Première année BTP Algorithmique avancée


3. TRI

Tri par insertion

Première année BTP Algorithmique avancée


3. TRI

Tri par insertion


Insérer un élément dans une liste déjà triée. Imaginer un joueur de cartes qui dispose des
cartes triées dans sa main gauche, et une carte dans la main droite, Il va placer cette carte
dans la main gauche de façon à ce qu'elle reste triée.
Au départ, la main gauche est vide, donc elle bien triée. À chaque fois que l'on insère une
carte depuis la main droite, la main gauche reste triée.

Pour un tableau, on décale les éléments plus grand que celui à insérer vers la droite
jusqu'au moment où on tombe sur un élément plus petit que celui qu'on veut insérer, qu'il
ne faut pas décaler.

Première année BTP Algorithmique avancée


3. TRI

Tri par insertion: Tableau


Insérer un élement dans un tableau trié:
void inserer(double elt_inserer, double tab[], int taille_g) {
int i;
for (i = taille_g; i > 0 && tab[i-1] > elt_inserer; i--) tab[i] = tab[i-1];
tab[i] = elt_inserer;
}
Tab[Taille_g]

Le tri complet est donc :


void tri_insertion(double tab[], int taille) {
int i;
for(i = 1; i < taille; ++i)
inserer(tab[i], tab, i);
}

Première année BTP Algorithmique avancée


3. TRI

Démonstration

Première année BTP Algorithmique avancée


3. TRI

Exercice

En s’inspirant du programme précédent qui tri par


insertion les éléments d’un tableau, écrire une fonction
qui tri par insertion la liste chaînée.

void Insertion_Valeur (liste *ListeTrie, liste V)


si ListeTrie est NULL ou ListeTrie->data>V alors insertion au debut
sinon on cherche precedent de la liste dont le suivant est plus grand que V.

liste Tri_Insertion (liste li)

Première année BTP Algorithmique avancée


3. TRI

Insertion d’1 élément : liste triée

void Insertion_Valeur (liste *ListeTrie, liste V) {


liste Precedent, Courant, A_inserer;

if (((*ListeTrie) == NULL)||(((*ListeTrie)->data) > V->data))


Insertion_Tete(ListeTrie,V->data) ;
else {
for (Courant = (*ListeTrie);(Courant != NULL) && (Courant->data < V->data);
Courant=Courant->suivant) Precedent = Courant ;

if (Courant == NULL) Insertion_Fin(*ListeTrie, V->data);


else {
A_inserer =(liste) malloc(sizeof(struct elem));
A_inserer->data = V->data;
A_inserer->suivant=Precedent->suivant,
Precedent->suivant =A_inserer;
}
}
}

Première année BTP Algorithmique avancée


3. TRI

Insertion d’1 élément : liste triée

void Insertion_Tete(liste *ListeTrie, double v){


liste nouveau;
nouveau=(liste) malloc(sizeof(struct elem));
nouveau->data=v;
nouveau->suivant = (*ListeTrie);
(*ListeTrie)=nouveau;
}

void Insertion_Fin(liste ListeTrie, double donnee) {


liste nouveau, courant;
nouveau = (liste) malloc (sizeof (struct elem));
courant=ListeTrie;
nouveau->data=donnee;
nouveau->suivant = NULL;
while(courant->suivant != NULL) { courant=courant->suivant; }
courant->suivant=nouveau;
}

Première année BTP Algorithmique avancée


3. TRI

Tri liste par insertion

liste Tri_Insertion (liste l) {


liste ListeTrie;
ListeTrie=(liste) malloc(sizeof(struct elem));
ListeTrie=NULL;
while (l != NULL) {
Insertion_Valeur (&ListeTrie, l);
l=l->suivant;
}
return ListeTrie;
}

Première année BTP Algorithmique avancée


3. TRI

Démonstration

Première année BTP Algorithmique avancée


3. TRI

Tri par fusion

Première année BTP Algorithmique avancée


3. TRI

Tri par fusion


Diviser pour régner : On coupe le tableau en deux parties, chaque sous tableau est de
nouveau divisé pour n'avoir plus qu'un seul élément.
On prend chaque deux éléments adjacents que l'on fusionne en les ordonnant. On
continue la fusion des sous tableaux générés jusqu’à la fin.

Première année BTP Algorithmique avancée


3. TRI

Tri par fusion

La fusion efficace repose sur le fait que les deux listes sont triées. on sait que les plus
petits éléments des deux listes sont au début, le plus petit élément de la liste globale
est donc forcément le plus petit le plus petit des deux.

Première année BTP Algorithmique avancée


3. TRI

Tri Fusion: Tableau


int toto(int i){
if (i>10) return;
i=i+1;
triFusion (T,début, fin) :
toto(i);
Si debut >= fin alors
printf("%s", "fffffffffffffff \n");
Arrêter
printf("%d \n",i);
Sinon
}
milieu = (debut+fin)/2
int main(int argc, char *argv[]) {
triFusion(T,début, milieu)
toto(5);
triFusion(T,milieu + 1, fin)
return 0;
fusionner(T,début, milieu, fin)
}
fffffffffffffff
11
fffffffffffffff
10
fffffffffffffff
9
fffffffffffffff
8
fffffffffffffff
7
fffffffffffffff
6

Première année BTP Algorithmique avancée


3. TRI

Découpage &fusion

Première année BTP Algorithmique avancée


3. TRI

fusion de deux tableaux triées


L'algorithme maintient trois pointeurs i,j et k, les deux premiers pour chacun des deux
tableaux et k pour maintenir l'index actuel du tableau trié final.
Est-ce que nous avons atteint la fin de l'un des tableaux?
-> Non
- Comparer les éléments actuels des deux tableaux (T1[i] et T2[j])
- Copiez l'élément le plus petit dans le tableau trié à la position k
- Déplacer le pointeur de l'élément contenant un élément plus petit (i ou j)
-> Oui
- Copiez tous les éléments restants du tableau non vide

Première année BTP Algorithmique avancée


3. TRI

Tri fusion : Tableau

void triFusion(int i, int j, double tab[]) {

if (j <= i) { return; }

int m = (i + j) / 2;

triFusion(i, m, tab); //trier la moitié gauche récursivement

triFusion(m + 1, j, tab); //trier la moitié droite récursivement

fusion(tab,i,m,j);
}

Première année BTP Algorithmique avancée


3. TRI
void fusion(double tab[], int i, int m, int j) {
double tmp[5];
int pg = i; //pg pointe au début du sous-tableau de gauche
int pd = m + 1; //pd pointe au début du sous-tableau de droite
int c; //compteur
// on boucle de i à j pour remplir chaque élément du tableau final fusionné
for(c = i; c <= j; c++) {
if(pg == m + 1) { //le pointeur du sous-tableau de gauche a atteint la limite
tmp[c] = tab[pd];
pd++;
}
else if (pd == j + 1) { //le pointeur du sous-tableau de droite a atteint la limite
tmp[c] = tab[pg];
pg++;
}else if (tab[pg] < tab[pd]) { // pointeur du sous-tableau de gauche pointe vers un élément plus petit
tmp[c] = tab[pg];
pg++;
}else { //le pointeur du sous-tableau de droite pointe vers un élément plus petit
tmp[c] = tab[pd];
pd++;
}
}
for(c = i; c <= j; c++) { //copier les éléments de tmp[] à tab[]
tab[c] = tmp[c];
}
}

Première année BTP Algorithmique avancée


3. TRI

Démonstration

Première année BTP Algorithmique avancée


3. TRI
Fusion de deux listes
liste fusion(liste L1, liste L2)
Variables
liste L3, p, q; // l3 liste fusionnée, pet q parcours de L1 et L2
Début
L3 ← NULL;
p ← L1;
q ← L2;
Tanque (p ≠ NULL) et (q ≠ NULL) Faire
Si (p->valeur <= q->valeur) Alors
Insertion_Fin(L3, p->valeur);
p ← p->suivant;
Sinon
Insertion_Fin(L3, q->valeur);
q ← q->suivant;
FinSi
FinFaire
Tanque (p ≠ NULL) Faire
Insertion_Fin(L3, p->valeur);
p ← p->suivant;
FinFaire
Tanque (q ≠ NULL) Faire
Insertion_Fin(L3, q->valeur);
q ← q->suivant;
FinFaire
return L3;
Fin
Première année BTP Algorithmique avancée
3. TRI

Fusion de deux listes

Liste Fusion(liste L1, liste L2)


{
liste L3, p, q;
L3=NULL;
p=L1;
q=L2;
while (p && q)
if (p->valeur <= q->valeur) {
Insertion_Fin (&L3, p->valeur);
p=p->suivant;
}
else {
Insertion_Fin(&L3, q->valeur);
q=q->suivant;
}
while (p) {
Insertion_Fin(&L3, p->valeur);
p=p->suivant; }
while (q) {
Insertion_Fin(&L3, q->valeur);
q=q->suivant; }
return L3;
}

Première année BTP Algorithmique avancée


3. TRI

liste fusion(liste a, liste b){ else{


// x pointe vers le premier element de la liste fusionee, if( fin_x == NULL ){
// fin_x pointe vers le dernier element de la liste fusionee x = b;
}
liste x = NULL, fin_x = NULL; else{
fin_x->suivant = b;
while( a != NULL && b!= NULL ){ }
if( a-> data < b-> data ){ fin_x = b;
if( fin_x == NULL ){ b=b->suivant;
x = a; }
} } /* fin while */
else{
fin_x->suivant = a; if( a == NULL )
} fin_x->suivant = b;
fin_x = a; else
a=a->suivant; fin_x->suivant = a;
} return x;
}
Première année BTP Algorithmique avancée
3. TRI

Tri avec fusion : Liste

liste tri_fusion(liste l, int longueur){


liste a,b,x,y;
int i;
if(longueur <=1) return l;

/* diviser la liste li en deux listes l et b de même longueur */


for( a = l, i = 0 ; i < longueur/2 - 1 ; i++, a=a->suivant) ;
b = a->suivant ;
a->suivant = NULL;
x = tri_fusion(l,longueur/2);
y = tri_fusion(b, longueur - longueur/2);

return fusion(x,y);
}

Première année BTP Algorithmique avancée


3. TRI

Démonstration

Première année BTP Algorithmique avancée


3. TRI

Test de performance des trois


algorithmes de Tri
clock_t deb,fin;
tab[i]=rand()%100;
debut=clock();
tri_selection ( l);
fin=clock();
printf("temps ecoule : %f\n",(double) (fin-debut)/ CLOCKS_PER_SEC);

Imane.abl.2000@gmail.com
Première année BTP Algorithmique avancée
4. Listes doublement chaînées

Liste doublement chaînées

A la différence des listes simplement chaînées, les maillons d'une liste doublement
chaînée possèdent un autre pointeur sur l'élément qui les précède :
4. Listes doublement chaînées

listes doublement chaînées

Le pointeur précédent du premier élément doit pointer vers NULL (le début de la liste).
Le pointeur suivant du dernier élément doit pointer vers NULL (la fin de la liste).

Pour accéder à un élément la liste peut être parcourue dans les deux sens :
en commençant avec la tête, le pointeur suivant permettant le déplacement vers le prochain élément.
en commençant avec la queue, le pointeur précédent permettant le déplacement vers l'élément
précédent.

Première année BTP Algorithmique avancée


4. Listes doublement chaînées

typedef struct dElement


{
char *donnee;
struct dElement *precedent;
struct dElement *suivant;
}dl_Element;

Pour avoir le contrôle de la liste il est préférable de sauvegarder certains


éléments : le premier élément, le dernier élément, le nombre d'éléments.
Pour réaliser cela une autre structure sera utilisée (ce n'est pas obligatoire,
des variables peuvent être utilisées).
Voici sa composition :
typedef struct dListe
{
dElement *debut;
dElement *fin;
int taille;
}dl_Liste;
Première année BTP Algorithmique avancée
4. Listes doublement chaînées
Initialisation void initialisation (dl_iste *liste){
liste->debut = NULL;
liste->fin = NULL;
taille = 0; }

Insertion d'un élément au une liste vide

int insertion_dans_liste_vide (dl_Liste * liste, char *donnee)


{
dl_Element *nouveau_element;
if ((nouveau_element = alloc (nouveau_element)) == NULL) return -1;
strcpy (nouveau_element->donnee, donnee);
nouveau_element->precedent = liste->debut;
nouveau_element->suivant = liste->fin;
liste->debut = nouveau_element;
liste->fin = nouveau_element;
liste->taille++;
return 0;}
Première année BTP Algorithmique avancée
4. Listes doublement chaînées
Insertion au début de la liste

int ins_debut_liste (dl_Liste * liste, char *donnee){


dl_Element *nouveau_element;
if ((nouveau_element = alloc (nouveau_element)) == NULL) return -1;
strcpy (nouveau_element->donnee, donnee);
nouveau_element->precedent = NULL;
nouveau_element->suivant = liste->debut;
liste->debut->precedent = nouveau_element;
liste->debut = nouveau_element;
liste->taille++;
return 0;}

Première année BTP Algorithmique avancée


4. Listes doublement chaînées

int ins_fin_liste (dl_Liste * liste, char *donnee){


dl_Element *nouveau_element;
if ((nouveau_element = alloc (nouveau_element)) == NULL)
return -1;
strcpy (nouveau_element->donnee, donnee);
nouveau_element->suivant = NULL;
nouveau_element->precedent = liste->fin;
liste->fin->suivant = nouveau_element;
liste->fin = nouveau_element;
liste->taille++; return 0;}

Première année BTP Algorithmique avancée


4. Listes doublement chaînées

int ins_avant (dl_Liste * liste, char *donnee, int pos){


int i;
dl_Element *nouveau_element, *courant;
if ((nouveau_element = alloc (nouveau_element)) == NULL)
return -1;
strcpy (nouveau_element->donnee, donnee);
courant = liste->debut;
for (i = 1; i < pos; ++i) courant = courant->suivant;
nouveau_element->suivant = courant;
nouveau_element-> precedent = courant->precedent;
if(courant->precedent == NULL)
liste->debut = nouveau_element;
else
courant->precedent->suivant = nouveau_element;
courant->precedent = nouveau_element;
liste->taille++;
return 0;
}

Première année BTP Algorithmique avancée


4. Listes doublement chaînées

Suppression d’un élément de la liste

Si dernier Si Premier

Première année BTP Algorithmique avancée


4. Listes doublement chaînées

int supp(dl_Liste *liste, int pos){


int i;
dl_Element *supp_element,*courant;
if(liste->taille == 0) return -1;
if(pos == 1){ /* suppresion de 1er élément */
supp_element = liste->debut;
liste->debut = liste->debut->suivant;
if(liste->debut == NULL) liste->fin = NULL;
else liste->debut->precedent == NULL; }
else if(pos == liste->taille){ /* suppression du dernier élément */
supp_element = liste->fin;
liste->fin->precedent->suivant = NULL;
liste->fin = liste->fin->precedent; }
else { /* suppression ailleurs */
courant = liste->debut;
for(i=1;i<pos;++i) courant = courant->suivant;
supp_element = courant;
courant->precedent->suivant = courant->suivant;
courant->suivant->precedent = courant->precedent; }
free(supp_element->donnee);
free(supp_element); liste->taille--;
return 0; }

Première année BTP et GM Algorithmique avancée

Vous aimerez peut-être aussi