TD4_DEV51_Qualite_Algo/Readme.md

159 lines
5.9 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#### **Exercice 1**
1. **`function_1(tableau1, tableau2)`** :
Dans cette fonction, il y a deux boucles imbriquées : la première parcourt tous les éléments de `tableau1` (de taille \(n\)), et pour chaque élément, la deuxième boucle parcourt `tableau2` (de taille \(m\)).
Dans le pire des cas, si aucun élément ne correspond (ou si le `break` n'est jamais atteint), chaque élément de `tableau1` sera comparé à tous les éléments de `tableau2`.
Donc, la complexité de cette fonction est \( O(n \cdot m) \).
2. **`function_2(x)`** :
Ici, on a une boucle `while` qui sexécute \(x\) fois. À chaque itération, on effectue une addition et une décrémentation, qui prennent toutes les deux un temps constant.
Du coup, la complexité est proportionnelle à \(x\), donc \( O(x) \).
3. **`function_3(x)`** :
Cette fonction contient uniquement des blocs `if` indépendants, qui sexécutent chacun au maximum une seule fois. Il ny a pas de boucle, donc chaque opération est constante.
La complexité est donc \( O(1) \), car cest constant peu importe la valeur de \(x\).
---
#### **Exercice 2**
Pour analyser la complexité de la fonction **`sort_students`**, on décompose chaque étape :
1. **Boucle externe sur les grades** :
La boucle externe parcourt tous les grades des étudiants, soit \( \text{grades\_number} \) itérations.
2. **Allocation dynamique des notes** :
Lallocation du tableau `grades` est faite avec `malloc`, qui est supposée avoir une complexité \( O(1) \). Cela naffecte donc pas significativement la complexité globale.
3. **Copie des notes des étudiants** :
Dans la boucle interne :
```c
for(j = 0; j < students_number; j++) {
grades[j] = students_array[j][i];
}
```
on copie les notes des \( \text{students\_number} \) étudiants, ce qui prend \( O(\text{students\_number}) \) par itération de la boucle externe.
4. **Tri des notes avec `bubblesort`** :
La fonction `bubblesort` trie un tableau de taille \( \text{students\_number} \), avec une complexité \( O(\text{students\_number}^2) \).
5. **Trouver le rang de chaque étudiant** :
Ensuite, dans cette boucle interne :
```c
for(j = 0; j < students_number; j++) {
students_rank[j][i] = find_rank_student(students_array[j][i], grades, students_number);
}
```
on appelle `find_rank_student` pour chaque étudiant. Cette fonction effectue :
- Un tri par bulles \( O(\text{students\_number}^2) \),
- Une recherche pour trouver le rang, qui prend \( O(\text{students\_number}) \).
Donc, chaque appel à `find_rank_student` a une complexité totale de \( O(\text{students\_number}^2) \), et cette fonction est appelée \( \text{students\_number} \) fois par itération de la boucle externe. Cela donne une complexité \( O(\text{students\_number}^3) \) par itération de la boucle externe.
6. **Libération de mémoire** :
Enfin, la mémoire allouée pour `grades` est libérée avec `free`, ce qui est une opération \( O(1) \).
### Complexité totale :
La boucle externe sexécute \( \text{grades\_number} \) fois, et la partie la plus coûteuse de la boucle interne est \( O(\text{students\_number}^3) \). La complexité globale de la fonction est donc :
\[
O(\text{grades\_number} \cdot \text{students\_number}^3)
\]
### Conclusion :
La fonction **`sort_students`** a une complexité algorithmique de **\( O(\text{grades\_number} \cdot \text{students\_number}^3) \)**.
---
#### **Exercice 3**
### **Algorithme proposé**
Pour trier un tableau à \( N \)-dimensions avec \( M \) valeurs par dimension, voici l'algo.
#### Étapes de lalgorithme :
1. Si on est au niveau dun tableau 1D (dimension la plus basse), on le trie directement.
2. Sinon :
- Trier chaque sous-dimension récursivement.
- Calculer la somme des valeurs de chaque sous-dimension.
- Trier les sous-dimensions en fonction de leurs sommes.
### **Implémentation en Python**
Voici lalgorithme en code:
```python
def recursive_sort(T):
# Si c'est un tableau 1D, on le trie directement
if not isinstance(T[0], list):
return sorted(T)
# Sinon, on trie chaque sous-dimension récursivement
for i in range(len(T)):
T[i] = recursive_sort(T[i])
# Puis on trie le tableau actuel selon la somme des sous-dimensions
T.sort(key=lambda x: sum(sum(val) if isinstance(val, list) else val for val in x))
return T
# Exemple avec un tableau 2D
tableau = [[0, 3, 2], [9, 4, 5], [4, 1, 3]]
resultat = recursive_sort(tableau)
print(resultat) # Résultat attendu : [[0, 2, 3], [1, 3, 4], [4, 5, 9]]
```
### **Exemple dexécution**
Pour le tableau donné :
\[ [ [0, 3, 2], [9, 4, 5], [4, 1, 3] ] \]
1. **Trier chaque ligne individuellement** :
\[
[ [0, 2, 3], [4, 5, 9], [1, 3, 4] ]
\]
2. **Calculer la somme des valeurs pour chaque ligne** :
- Première ligne : \( 0 + 2 + 3 = 5 \)
- Deuxième ligne : \( 4 + 5 + 9 = 18 \)
- Troisième ligne : \( 1 + 3 + 4 = 8 \)
3. **Trier les lignes en fonction de leurs sommes** :
\[
[ [0, 2, 3], [1, 3, 4], [4, 5, 9] ]
\]
### **Complexité de lalgorithme**
#### Analyse :
1. **Pour la dimension la plus basse (1D)** :
- Trier \( M \) éléments coûte \( O(M \log M) \).
2. **Pour les dimensions supérieures (\( N > 1 \))** :
- Chaque dimension contient \( M^{N-1} \) sous-tableaux.
- Trier ces sous-tableaux coûte \( O(M^{N-1} \log M^{N-1}) \).
- Calculer les sommes pour ces sous-tableaux prend \( O(M^N) \).
3. **Récursivité sur \( N \) dimensions** :
- La complexité totale est donnée par la somme :
\[
T(N, M) = O(M^N \log M + M^{N-1} \log M^{N-1} + \dots + M \log M)
\]
- La partie dominante est celle de la dimension principale :
\[
T(N, M) = O(M^N \log M)
\]
### **Conclusion**
- - La complexité globale est
\[
O(M^N \log M)
\]