Skip to content
Snippets Groups Projects
Verified Commit 903464d9 authored by orestis.malaspin's avatar orestis.malaspin
Browse files
parents 50941940 17fb206b
No related branches found
No related tags found
No related merge requests found
Showing
with 428 additions and 0 deletions
# Algorithmes et structures de données
# Deux applications des piles
*****
## La transformation infixe $\Leftarrow$ postfixe
Exemples:
| Expression infixe | | Expression postfixe |
|-----------------------|------------------|---------------------|
| A + B * C | transformé en | A B C * + |
| A + (B / C – D ^ E ) | transformé en | A B C / D E ^ – + |
A chaque opérateur, on associe une priorité, par exemple:
| Opérateur | Priorité |
|-----------|----------|
| ^ | 3 |
| *, / | 2 |
| +, - | 1 |
L'algorithme utilise une pile dans laquelle on stocke les opérateurs et les parenthèses ouvertes
rencontrées dans l'expression.
Les étapes sont les suivantes :
1. Examiner le prochain caractère dans l'expression donnée.
2. Si c'est un opérande, le mettre directement dans l'expression du résultat.
3. Si c'est une parenthèse ouverte, la mettre dans la pile avec la priorité zéro.
4. Si c'est un opérateur, comparer sa priorité avec celle de l'élément au sommet de la pile:
* Si la priorité de l'opérateur est plus grande que l'opérateur du sommet de la pile, empiler ce nouvel opérateur.
* Sinon prendre l'opérateur du sommet de la pile, le mettre dans l'expression du résultat et répéter la comparaison avec le nouveau sommet de la pile, jusqu'à ce qu'un opérateur de priorité inférieure à celle de l'opérateur de l'expression apparaisse au sommet de la pile ou jusqu'à ce que la pile soit vide.
5. Si c'est une parenthèse fermée, enlever de la pile les opérateurs et les placer dans l'expression du résultat jusqu'à ce qu'une parenthèse ouverte apparaisse au sommet de la pile, se défaire de cette parenthèse.
6. Si l'expression donnée est vide, enlever de la pile les opérateurs restants et les placer dans l'expression du résultat.
La table ci-dessous montre la réalisation d'une transformation infixe - postfixe sur une expression algébrique (supposée syntaxiquement correcte):
![Exemple de transformation infixe-postfixe](./figures/fig_transf_infixe_postfixe.png)
**Remarque:** On utilise aussi d'autres structures de données pour traiter ce problème. Entre autres les arbres.
## L'évaluation d'une expression en notation postfixée
La manière la plus simple de procéder est d'utiliser une pile contenant à chaque instant les valeurs des opérandes déjà calculés.
Dans une expression donnée sous forme postfixée, chaque opérateur porte sur les opérandes qui le précédent immédiatement, ceux ci doivent toujours se trouver en tête de pile au moment de l'opération. Le résultat d'une opération est un nouvel opérande qui est remis au sommet de la pile pour la suite de l'évaluation.
Les règles d'évaluation sont les suivantes:
* la valeur d'un opérande est toujours empilée.
* Un opérateur s'applique toujours aux 2 opérandes en tête de pile.
* Le résultat de l'opération est remis en tête de pile.
Exemple:
Soit l'expression postfixe à évaluer: A B C + * D -
| Caractères lus | Pile des opérandes (nombres) |
|----------------|------------------------------|
| A | A |
| B | A, B |
| C | A, B, C |
| + | A, B+C |
| * | A*(B+C) |
| D | A*(B+C), D |
| A | *(B+C)-D |
La pile contient finalement la valeur de l'expression.
Ce traitement exige naturellement que l'expression à évaluer soit syntaxiquement correcte.
\ No newline at end of file
# Algorithmes et structures de données
# Structure de pile
*****
## 1. Définition
Une pile est une structure de données dans laquelle la dernière information entrée, est la première à ressortir (en anglais : LIFO, Last In First Out)
On envisage deux types d'implémentation de piles:
1. l'une à capacité limitée (piles dénommées statiques);
2. l'autre à capacité « infinie » (piles dénommées dynamiques dont la capacité limite dépend en réalité de la mémoire disponible).
## 2. Spécification de la structure
Le type des éléments qu'on empile, n'étant pas précisé, on parle de spécification générique.
Les opérations possibles sur une pile en définissent l'interface :
* Opérations de manipulation
* Empiler un nouvel élément sur la pile
* Dépiler l'élément au sommet de la pile (i.e. le dernier élément introduit)
* Fonctions de consultation
* Lire l'élément au sommet de la pile
* Tester si la pile est vide
* Tester si la pile a atteint la capacité maximale, seulement dans le cas d'une pile statique
* L'interface de la pile est l'ensemble des fonctionnalités offertes à l'utilisateur pour interagir avec une pile
## 3. Quelques applications des piles
* Gérer les mécanismes internes de mise en œuvre de la récursivité
* Traiter les structures imbriquées
* Implémenter les machines abstraites
* Passer les paramètres aux procédures
* Sauver l'état d'un processus
\ No newline at end of file
# Algorithmes et structures de données
# Structure de file d'attente
*****
## 1. Définition
Une file d'attente ou queue est une structure de données dans laquelle la première information entrée est la première à ressortir (en anglais : FIFO, First In First Out)
On considère ici une implémentation de queue dynamique et donc à capacité « infinie » (dépend en réalité de la mémoire disponible).
## 2. Spécification de la structure
Si le type des éléments qu'on insère, n'est pas précisé, on parle de spécification générique.
Les opérations possibles sur une file d'attente (ou queue) en définissent l'interface :
* Opérations de manipulation
* Créer une liste vide
* Détruire une liste
* Insérer un nouvel élément en queue de la file d'attente
* Extraire un élément en tête de la file d'attente (i.e. le premier élément introduit)
*
* Fonctions de consultation
* Lire l'élément en tête de la file d'attente
* Lire l'élément en queue de la file d'attente
* Tester si la file d'attente est vide
L'interface de la file d'attente est l'ensemble des fonctionnalités offertes à l'utilisateur pour interagir
avec celle-ci.
## 3. Structure de file d'attente
On considère une liste chaînée d'articles avec deux pointeurs de tête et de queue. Chaque article comportera un champ pour stocker les valeurs dans cette liste et un champ contenant une variable de type accès pour assurer le chaînage. On considère à titre d'exemple le cas de valeurs entières.
Schématiquement:
![Illustration d'une file d'attente](./figures/fig_queue_representation.png)
L'accès à la file d'attente se fera par les pointeurs de tête et de queue.
Une telle file d'attente basée sur une liste chaînée sera déclarée par exemple sous la forme suivante:
```C
struct _element { // Elément de liste
int data;
struct _element* next;
} element;
struct _queue { // File d'attente:
element* tete; // tête de file d'attente
element* debut; // queue de file d'attente
}
```
## 4. Implémentation des fonctionnalité d'une file d'attente
### a) Consultations
On considère la fonction queue_est_vide qui teste si la file d'attente est vide et les fonctions `queue_tete` et `queue_debut` qui retournent l'élément en tête, respectivement en queue, de la file d'attente.
```C
bool queue_est_vide(queue fa) {
return (NULL == fa.tete && NULL == fa.debut);
}
int queue_tete(queue fa) {
assert(!queue_est_vide(fa));
return fa.tete­>data;
}
int queue_debut(queue fa) {
assert(!queue_est_vide(fa));
return fa.debut­>data;
}
```
### b) Manipulations
#### Insertion en queue de file d'attente
Voici l'entête de la fonction: `void queue_inserer(queue* fa,int val);`
Il faut considérer plusieurs cas:
* La file d'attente est vide
![Insertion dans une file d'attente vide](./figures/fig_empty_queue_insert.png)
* L'insertion se fait en queue d'une file d'attente non vide
![Insertion dans une file d'attente non-vide](./figures/fig_non_empty_queue_insert.png)
#### Extraction en tête de file d'attente
Voici l'entête de la procédure: `int queue_extraire(queue* fa);`
On commence par récupérer, la valeur en tête de file d'attente via l'appel `queue_tete(*fa);`
Puis on met un pointeur temporaire sur l'élément en tête, avant de déplacer le pointeur de tête sur l'élément suivant.
Finalement, on désalloue la mémoire
![Extraction d'une file d'attente](./figures/fig_queue_extract.png)
Si la file d'attente n'avait qu'un seul élément, alors il faudrait mettre le pointeur `fa-­>debut` à `NULL`.
Dans ce cas, à la suite du point (3), le pointeur `fa-­>tete` se retrouve à `NULL`. On doit donc ajouter l'instruction :
```C
if (NULL == fa­>tete) {
fa­>debut = NULL;
}
```
# Algorithmes et structures de données
# Structure de liste triée
*****
## 1. Définition
On considère une liste chaînée d'articles. Chaque article comportera un champ pour stocker les valeurs
dans la liste et un champ contenant une variable de type pointeur pour assurer le chaînage.
Schématiquement:
![Illustration d'une file d'attente](./figures/fig_queue_representation.png)
La liste est triée pour autant que l'insertion de chaque nouvelle valeur dans la liste maintienne cette
propriété.
L'accès à la liste se fera uniquement par le pointeur lst qui référence le début de la liste.
Une telle liste chaînée sera déclarée par exemple sous la forme suivante:
```C
typedef struct _element { // Elément de liste
int n;
struct _element* suivant;
} element;
typedef element* liste; // Pointeur sur des éléments de liste
```
## 2. Insertion dans une liste triée
Voici l'entête de la procédure : `liste inserer(liste lst,int val);`
Il faut considérer plusieurs cas.
### La liste est vide: `lst == NULL`
![Insertion dans une liste triée vide](./figures/fig_empty_sorted_list_insert.png)
### L'insertion se fait en 1ère position: `val <= lst->n`
Par exemple, pour `val = 1`
![Insertion en 1ère position d'une liste triée](./figures/fig_1st_position_sorted_list_insert.png)
### Les positions autres que la 1ère position
Par exemple, pour `val = 13`
![Insertion aux autres positions d'une liste triée](./figures/fig_other_position_sorted_list_insert.png)
```C
(1) tmp = malloc(sizeof(element));
tmp->n = 13;
```
On déplace un pointeur crt jusqu'à l'élément précédent la position d'insertion de sorte que
```C
crt->n < val <= crt->suivant->n
```
On utilise une boucle:
```C
(2) while (NULL != crt->suivant && val > crt->suivant->n) {
crt = crt->suivant;
}
```
Puis on raccroche l'élément pointé par tmp à la liste
```C
(3) tmp->suivant = crt->suivant;
(4) crt->suivant = tmp;
return lst;
```
## 3. Extraction d'un élément dans une liste triée
Voici l'entête de la procédure : `liste extraire(liste lst,int val);`
Si la liste est vide, on retourne la liste vide.
Ensuite, on déplace deux pointeurs prec et crt à travers la liste jusqu'à ce que : `prec->n < val <= crt->n`
On utilise une boucle:
```C
while (NULL != crt && val > crt->n) {
prec = crt;
crt = crt->suivant;
}
```
Il faut à nouveau considérer plusieurs cas.
### La valeur à retirer est supérieure à la dernière valeur de la liste.
Ceci équivaut à: `crt == NULL` ou `prec->suivant == NULL`
On retourne la liste inchangée.
Par exemple, pour `val = 30`
![Extraction d'une valeur supérieure à la dernière valeur d'une liste triée](./figures/fig_greater_value_sorted_list_extract.png)
### La valeur à retirer n'est pas celle dans l'élément pointé par `crt`.
Ceci équivaut à: `val < crt->n`
On retourne la liste inchangée.
Par exemple, pour `val = 9`
![Extraction d'une valeur pas dans une liste triée (1)](./figures/fig_no_value_sorted_list_extract_1.png)
ou pour val = 1
![Extraction d'une valeur pas dans une liste triée (2)](./figures/fig_no_value_sorted_list_extract_2.png)
### La valeur à retirer est celle dans l'élément pointé par `crt`.
Ceci équivaut à: `val == crt->n`
#### La valeur à retirer est en début de liste.
Ceci équivaut à: `crt == prec`
On doit déplacer la tête de liste : lst = crt->suivant;
Par exemple, pour `val = 3`
![Extraction d'une valeur en début de liste triée ](./figures/fig_1st_element_sorted_list_extract.png)
#### La valeur à retirer n'est pas en début de liste.
On doit raccrocher l'élément pointé par prec à celui suivant `crt`: `prec->suivant = crt->suivant;`
Par exemple, pour `val = 12`
![Extraction d'une valeur pas en début de liste triée](./figures/fig_other_element_sorted_list_extract_1.png)
ou pour `val = 21`
![Extraction d'une valeur pas dans une liste triée (1)](./figures/fig_other_element_sorted_list_extract_2.png)
Finalement, on libère la mémoire de l'élément pointé par `crt`: `free(crt);`
![Extraction d'une valeur pas dans une liste triée (1)](./figures/fig_free_element_sorted_list_extract.png)
## 4. Recherche dans une liste triée
La fonction recherche retourne un pointeur sur l'élément qui contient la valeur recherchée ou un pointeur `NULL` si la valeur est absente de la liste triée.
Voici l'entête de la procédure : `element* recherche(liste lst,int val);`
On considère d'abord la fonction utilitaire `position` qui retourne un pointeur sur l'élément avant la
position d'insertion d'une valeur ou un pointeur `NULL` s'il s'agit de la tête de liste.
```C
element* position(liste lst,int val) {
element* pos = lst;
if (est_vide(lst) || val <= lst->n) {
pos = NULL;
} else {
while (NULL != pos->suivant && val > pos->suivant->n) {
pos = pos->suivant;
}
}
return pos;
}
```
Par exemple, pour val = 1 ou 3
![Recherche d'une valeur en début de liste triée](./figures/fig_1st_element_sorted_list_search.png)
et pour val = 29
![Recherche d'une valeur en fin de liste triée](./figures/fig_last_element_sorted_list_search.png)
et finalement pour val = 10 ou 12
![Recherche d'une valeur en milieu de liste triée](./figures/fig_other_element_sorted_list_search.png)
Ainsi, la fonction de recherche s'écrit simplement :
```C
element* recherche(liste lst,int val) {
element* pos = position(lst,val);
if (est_vide(lst)) {
return NULL;
}
if (NULL == pos && val == lst->n) {
return lst;
} else if (NULL != pos->suivant && val == pos->suivant->n) {
return pos->suivant;
} else {
return NULL;
}
}
```
## Exercice
Ecrire directement la fonction `recherche` sans utiliser la fonction `position`.
Faire les dessins illustrant les différents cas possibles.
lessons/figures/fig_1st_element_sorted_list_extract.png

9.01 KiB

lessons/figures/fig_1st_element_sorted_list_search.png

43.3 KiB

lessons/figures/fig_1st_position_sorted_list_insert.png

20.5 KiB

lessons/figures/fig_empty_queue_insert.png

19.8 KiB

lessons/figures/fig_empty_sorted_list_insert.png

12.7 KiB

lessons/figures/fig_free_element_sorted_list_extract.png

109 KiB

lessons/figures/fig_greater_value_sorted_list_extract.png

6.73 KiB

lessons/figures/fig_last_element_sorted_list_search.png

31.1 KiB

lessons/figures/fig_no_value_sorted_list_extract_1.png

6.44 KiB

lessons/figures/fig_no_value_sorted_list_extract_2.png

6.91 KiB

lessons/figures/fig_non_empty_queue_insert.png

29.3 KiB

lessons/figures/fig_other_element_sorted_list_extract_1.png

116 KiB

lessons/figures/fig_other_element_sorted_list_extract_2.png

113 KiB

lessons/figures/fig_other_element_sorted_list_search.png

38.3 KiB

lessons/figures/fig_other_position_sorted_list_insert.png

12 KiB

lessons/figures/fig_queue_extract.png

23.7 KiB

0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment