Les Piles

Télécharger au format pdf ou txt
Télécharger au format pdf ou txt
Vous êtes sur la page 1sur 33

CHP 3: PILES, LES

FILES ET LES LISTES.

LAWSON Latevi Sena.


LISTES
3.12.1 LISTES SIMPLES : DÉFINITION

❏ Une liste simple est une structure de données.


❏ Elle consiste en un ensemble d'objets de même type.
❏ Les éléments de la liste sont reliés les uns aux autres.
❏ Chaque élément contient des données caractéristiques de l'application.
❏ Chaque élément possède un pointeur vers l'élément suivant ou une marque de fin.
❏ Utile pour gérer des collections d'objets avec des ajouts et des suppressions fréquents.
Importance des listes
❏ Stockage de Données Multiples
❏ Structuration des informations.
❏ Adaptabilité à divers types de données.
❏ Accès Efficace aux Éléments
❏ Accès en temps constant par index.
❏ Modification Facile
❏ Ajout, suppression, mise à jour d'éléments.
❏ Itération
❏ Parcours et manipulation des éléments.
❏ Structures de Données Complexes
❏ Possibilité d'imbrication pour des structures avancées.
❏ Tri et Recherche
❏ Facilite le tri et la recherche d'éléments.
❏ Implémentation d'Algorithmes
❏ Base pour de nombreuses structures de données.
❏ Gestion de Collections de Données
❏ Utile pour gérer des ensembles d'informations.
❏ Passage d'Informations entre Fonctions
❏ Transmission cohérente de données entre fonctions.
❏ Simplicité et Lisibilité du Code
❏ Permet une programmation propre et lisible.
❏ Fondamental en programmation et gestion de données.
❏ Utilisation variée : informatique, sciences, finance, etc
Applications des Listes.
1.1 Listes chaînée Simple.
1.1 Listes chaînée Simple.
#include <stdio.h> struct Node { struct Node* createNode(int data) {
#include <stdlib.h> int data; struct Node* newNode = (struct
les bibliothèques standard en C. struct Node* next; Node*)malloc(sizeof(struct Node));
<stdio.h> est nécessaire pour les }; if (newNode == NULL) {
opérations d'entrée/sortie, et <stdlib.h> La structure struct Node, qui perror("Erreur lors de l'allocation de
est nécessaire pour les fonctions représente un nœud dans la liste mémoire pour le nœud");
d'allocation de mémoire et de gestion de chaînée. Chaque nœud contient
l'erreur.
exit(1);
deux champs : data pour stocker }
la valeur de l'élément et next pour
pointer vers le nœud suivant.
newNode->data = data;
newNode->next = NULL;
return newNode;
void appendNode(struct Node** head, int data) {
}
struct Node* newNode = createNode(data);
Cette fonction createNode prend une valeur en
if (*head == NULL) { argument et crée un nouveau nœud en allouant
*head = newNode; dynamiquement de la mémoire pour le nœud. Si
} else { l'allocation de mémoire échoue, elle affiche un
struct Node* current = *head; message d'erreur et quitte le programme. Sinon, elle
while (current->next != NULL) { initialise les champs data et next du nœud avec les
valeurs appropriées et renvoie un pointeur vers le
current = current->next;
nouveau nœud
}
current->next = newNode;
}
1.1 Listes chaînée Simple.
void displayList(struct Node* head) { int main() {
struct Node* current = head; struct Node* myList = NULL;
while (current != NULL) { appendNode(&myList, 1);
printf("%d -> ", current->data); appendNode(&myList, 2);
current = current->next; appendNode(&myList, 3);
} printf("Liste : ");
printf("NULL\n"); displayList(myList);
}
return 0;
La fonction displayList prend un pointeur }
vers la tête de la liste et affiche les éléments
de la liste en parcourant la liste du début à Dans la fonction main, une liste chaînée vide est créée en initialisant
la fin. Elle imprime la valeur de chaque myList à NULL. Ensuite, trois éléments (1, 2, 3) sont ajoutés à la liste en
nœud, suivi de "->", et à la fin de la liste, elle utilisant la fonction appendNode. Enfin, la liste est affichée en utilisant la
imprime "NULL" pour indiquer la fin de la fonction displayList, et le programme se termine avec un code de
liste. retour 0.
1.1 Listes chaînée ordonnée.
1.1 Listes chaînée ordonnée.
void insertSorted(struct Node** head, int data) {
La fonction insertSorted est responsable de l'insertion d'un nouvel
struct Node* newNode = createNode(data);
élément trié dans la liste chaînée. Elle prend un pointeur vers le pointeur
de la tête de la liste (**head) et la valeur data à insérer. La fonction crée
if (*head == NULL || data < (*head)->data) {
d'abord un nouvel élément à insérer en utilisant createNode.
newNode->next = *head;
*head = newNode;
Ensuite, elle vérifie si la liste est vide ou si l'élément doit être inséré au
} else { début de la liste (car data est inférieur à la valeur du premier élément). Si
struct Node* current = *head; c'est le cas, elle met à jour la tête de la liste pour pointer vers le nouvel
while (current->next != NULL && élément.
current->next->data < data) {
current = current->next; Sinon, la fonction parcourt la liste à l'aide d'une boucle while pour trouver
} la bonne position d'insertion. Elle insère ensuite le nouvel élément dans la
newNode->next = current->next; liste tout en maintenant l'ordre trié
current->next = newNode;
}
}
Liste chaînée circulaire
Liste chaînée circulaire
void append(struct Node** head, int data) { La fonction append permet d'ajouter un nouvel élément à la liste
struct Node* newNode = createNode(data); chaînée circulaire. Elle prend un pointeur vers la tête de la liste (**head)
if (*head == NULL) { et la valeur data à insérer.
*head = newNode;
newNode->next = *head; Si la liste est vide (c'est-à-dire, *head est NULL), elle initialise la tête de
} else { la liste avec le nouvel élément et crée une boucle en faisant pointer le
struct Node* last = *head; newNode->next vers lui-même.
while (last->next != *head) {
Sinon, si la liste n'est pas vide, la fonction parcourt la liste à l'aide d'une
last = last->next;
boucle while pour trouver le dernier élément (celui dont le champ next
}
pointe vers la tête), puis insère le nouveau nœud à la fin de la liste en
last->next = newNode;
ajustant les pointeurs pour créer la boucle.
newNode->next = *head;
}
}
Liste chaînée circulaire
void printList(struct Node* head) {
struct Node* current = head; La fonction printList prend la tête de la liste comme argument et parcourt
do { la liste en utilisant une boucle do...while. Elle affiche la valeur de chaque
printf("%d -> ", current->data); élément et continue jusqu'à ce que le pointeur current revienne à la tête de
la liste, indiquant ainsi que c'est une liste chaînée circulaire. Elle affiche "...
current = current->next; (boucle)" pour indiquer que la liste est circulaire.
} while (current != head);
printf("... (boucle)\n");
}
Liste doublement chaînée
Liste doublement chaînée
#include <stdio.h> // Structure pour un élément de
#include <stdlib.h> // Fonction pour créer un nouvel élément de
liste doublement chaînée
liste
struct Node {
struct Node* createNode(int data) {
int data;
struct Node* newNode = (struct
struct Node* prev;
Node*)malloc(sizeof(struct Node));
struct Node* next;
if (newNode == NULL) {
};
perror("Erreur lors de l'allocation de
mémoire pour le nouveau nœud.");
// Fonction pour ajouter un élément à la fin de la liste exit(1);
doublement chaînée }
void append(struct Node** head, int data) { newNode->data = data;
struct Node* newNode = createNode(data); newNode->prev = NULL;
if (*head == NULL) { newNode->next = NULL;
*head = newNode; return newNode;
} else { }
struct Node* current = *head;
while (current->next != NULL) {
current = current->next;
}
current->next = newNode;
Liste doublement chaînée

// Fonction pour afficher la liste


doublement chaînée en avant // Fonction pour afficher la liste doublement chaînée en
void printForward(struct Node* head) { arrière
struct Node* current = head; void printBackward(struct Node* tail) {
while (current != NULL) { struct Node* current = tail;
printf("%d -> ", current->data); while (current != NULL) {
current = current->next; printf("%d -> ", current->data);
} current = current->prev;
printf("NULL\n"); }
} printf("NULL\n");
}
Liste doublement chaînée circulaire
Liste doublement chaînée circulaire
#include <stdio.h>
// Structure pour un élément de // Fonction pour créer un nouvel élément de liste
#include <stdlib.h>
liste doublement circulaire struct Node* createNode(int data) {
struct Node { struct Node* newNode = (struct
int data; Node*)malloc(sizeof(struct Node));
struct Node* prev; if (newNode == NULL) {
struct Node* next; perror("Erreur lors de l'allocation de mémoire pour
}; le nouveau nœud.");
exit(1);
}
newNode->data = data;
newNode->prev = NULL;
newNode->next = NULL;
return newNode;
}
Liste doublement chaînée circulaire
// Fonction pour ajouter un élément à la fin de la liste
doublement circulaire // Fonction pour afficher la liste doublement
void append(struct Node** head, int data) { circulaire en avant
struct Node* newNode = createNode(data); void printForward(struct Node* head) {
if (*head == NULL) { if (head == NULL) {
*head = newNode; printf("La liste est vide.\n");
newNode->prev = newNode; return;
newNode->next = newNode; }
} else { struct Node* current = head;
struct Node* tail = (*head)->prev; do {
tail->next = newNode; printf("%d -> ", current->data);
newNode->prev = tail; current = current->next;
newNode->next = *head; } while (current != head);
(*head)->prev = newNode; printf("... (boucle)\n");
} }
}
Liste doublement chaînée circulaire

// Fonction pour afficher la liste doublement circulaire en arrière


void printBackward(struct Node* head) {
if (head == NULL) {
printf("La liste est vide.\n");
return;
}

struct Node* tail = head->prev;


struct Node* current = tail;
do {
printf("%d -> ", current->data);
current = current->prev;
} while (current != tail);
printf("... (boucle)\n");
}
EXERCICES.
Exercice sur les listes chaînées simples en C :
Créez une structure de données en C pour représenter une liste chaînée simple
contenant
des entiers. Ensuite, écrivez des fonctions pour effectuer les opérations suivantes :
1. insertAtEnd: Une fonction pour ajouter un nouvel élément à la fin de la liste.
2. deleteElement: Une fonction pour supprimer un élément donné de la liste.
3. searchElement: Une fonction pour rechercher un élément donné dans la liste.
4. displayList: Une fonction pour afficher les éléments de la liste.
5. Testez ces fonctions en créant une liste, en ajoutant, supprimant, recherchant et
affichant les éléments.
Exercice sur les listes chaînées circulaires en C :
Créez une structure de données en C pour représenter une liste chaînée circulaire
contenant des entiers (ou des chaînes de caractères si vous le souhaitez).
Écrivez des fonctions pour réaliser les opérations suivantes :
1. insertAtEndCircular: Une fonction pour ajouter un nouvel élément à la fin de la
liste circulaire.
2. deleteElementCircular: Une fonction pour supprimer un élément donné de la liste
circulaire.
3. displayCircularList: Une fonction pour afficher les éléments de la liste circulaire.
4. Assurez-vous que la liste circulaire est correctement construite, de sorte que le
dernier élément pointe vers le premier, créant ainsi une boucle.
5. Testez ces fonctions en créant une liste circulaire, en ajoutant, supprimant et en
affichant les éléments de la liste.
LES PILES

LAWSON Latevi Sena.


LES PILES
❏ Une pile est une structure de données informatique qui suit le
principe LIFO (Last In, First Out).
❏ LIFO signifie que le dernier élément ajouté est le premier à être
retiré.
❏ Opérations principales :
❏ Empiler (push) : Ajouter un élément au sommet de la pile.
❏ Dépiler (pop) : Retirer l'élément supérieur de la pile.
❏ Utilisations courantes :
❏ Gestion de la pile d'appels dans les langages de
programmation.
❏ Suivi de l'historique des actions (p. ex. navigation Web).
❏ Résolution de problèmes algorithmiques.
❏ La pile est essentielle pour gérer des données de manière
séquentielle dans de nombreuses applications informatiques.
IMPLÉMENTATION EN C
Ce sont des directives de préprocesseur qui indiquent
#include <stdio.h> d'inclure les fichiers d'en-tête stdio.h et stdlib.h,
#include <stdlib.h> nécessaires pour l'entrée/sortie standard et les
fonctions liées à la mémoire dynamique,
respectivement.

struct Node { Définition de la structure Node qui représente un


int data; élément de la pile. Chaque nœud contient une
struct Node* next; donnée (data) de type entier et un pointeur vers le
}; nœud suivant (next).
IMPLÉMENTATION EN C
Définition de la structure Stack qui représente la pile. La
struct Stack { pile est essentiellement constituée d'un pointeur vers le
struct Node* top; sommet (top), qui pointe vers le nœud en haut de la pile.
};

void init(struct Stack* stack) {


La fonction init initialise la pile en mettant le pointeur top à
stack->top = NULL; NULL, indiquant une pile vide.
}

int isEmpty(struct Stack* stack) { La fonction isEmpty retourne 1 si la pile est vide (le
return stack->top == NULL;} pointeur top est NULL) et 0 sinon.
IMPLÉMENTATION EN C

void push(struct Stack* stack, int item) {


struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
if (newNode == NULL) {
printf("Erreur d'allocation mémoire, impossible d'empiler %d\n", item);
return;
}
newNode->data = item;
newNode->next = stack->top;
stack->top = newNode;
} La fonction push empile un nouvel élément sur la pile.
Elle alloue dynamiquement un nouveau nœud, y stocke la
donnée, et ajuste les pointeurs pour le nouveau sommet
de la pile.
IMPLÉMENTATION EN C
int pop(struct Stack* stack) {
if (isEmpty(stack)) {
printf("La pile est vide, impossible de dépiler\n");
return -1; // Valeur d'erreur
}
struct Node* temp = stack->top;
int data = temp->data; La fonction pop dépile l'élément en haut de la pile.
stack->top = temp->next; Elle vérifie d'abord si la pile est vide, puis elle
free(temp); récupère la donnée, ajuste le pointeur top et
return data; libère la mémoire du nœud dépilé.
}
IMPLÉMENTATION EN C

void display(struct Stack* stack) {


if (isEmpty(stack)) {
printf("La pile est vide.\n");
La fonction display affiche les éléments
return;
de la pile en parcourant les nœuds de
}
haut en bas.
printf("Contenu de la pile : ");
struct Node* current = stack->top;
while (current != NULL) {
printf("%d ", current->data);
current = current->next;
}
printf("\n");
}
IMPLÉMENTATION EN C
void clear(struct Stack* stack) { La fonction clear vide complètement la pile en
while (!isEmpty(stack)) { utilisant la fonction pop jusqu'à ce que la pile
pop(stack); soit vide.
}
}
int main() {
struct Stack stack;
init(&stack);
push(&stack, 10);
push(&stack, 20); La fonction main teste les opérations de
push(&stack, 30); la pile. Elle initialise une pile, y empile
display(&stack); trois éléments, affiche la pile, dépile un
printf("Élément dépilé : %d\n", pop(&stack));
display(&stack);
élément, réaffiche la pile, puis libère la
clear(&stack); // Libérer la mémoire de la pile mémoire de la pile.
return 0;}
EXERCICE SUR LES PILES

EXERCICE 1

Écrire un algorithme utilisant une pile (implémentée sous


forme de liste chaînée) qui affiche une liste chaînée
d’entiers à l’envers.
EXERCICE SUR LES PILES

EXERCICE 2

En notation postfixée, les opérateurs suivent leurs opérandes. Par exemple,


l'expression infixée "3 + 4" serait écrite en postfixé comme "3 4 +".

1. Écrivez une fonction en utilisant une pile pour évaluer une expression
postfixée. L'expression est donnée sous forme de chaîne de caractères et
peut contenir des entiers et des opérateurs binaires tels que '+', '-', '*', et '/'.
2. La fonction devrait retourner le résultat de l'évaluation.
3. Assurez-vous de gérer correctement les erreurs, par exemple, si
l'expression est mal formée.
EXERCICE SUR LES PILES
EXERCICE 3

Faites une implémentation des piles en utilisant les tableaux.

Vous aimerez peut-être aussi