Timsort
- Algorithme de Timsort
- Exemple de Timsort
- Implémentation de l’algorithme Timsort
- Complexité de l’algorithme de tri temporel
Tim sort est un algorithme de tri hybride stable. Il s’agit d’un algorithme hybride dérivé du tri par insertion et du tri par fusion. Il utilise d’abord des sous-réseaux utilisant le tri par insertion ; ces petits sous-réseaux triés sont appelés natural runs. Ces passages sont ensuite fusionnés en utilisant le tri par fusion pour produire des tableaux triés finaux. Il a été conçu en tenant compte des performances optimales de l’algorithme sur des données réelles. Il utilise le fait que le tri par insertion fonctionne très bien sur des sous-réseaux de petite taille. Il s’agit de l’algorithme de tri standard utilisé par Array.sort()
de Java et sorted()
et sort()
de Python.
Algorithme de Timsort
Supposons que nous ayons un tableau non trié A[]
contenant n
éléments. Nous considérerons que la taille de l’exécution est de 32
. Il peut s’agir de n’importe quelle puissance de 2
car la fusion est plus efficace lorsque les nombres sont de puissances de 2
.
TimSort()
-
Divisez le tableau en exécutions
n/32
. -
Trier les exécutions individuelles en utilisant le tri par insertion, une par une.
-
Fusionner les runs triés un par un en utilisant la fonction
merge
du tri fusion.
Merge()
-
Initialise le tableau auxiliaire
output
pour stocker la sortie triée. -
Initialise 3 pointeurs
i
,j
&k
.i
pointe vers le début du premier sous-tableaubeg
.
j
indique le début du deuxième sous-réseaumid + 1
.
k
initialisée avecbeg
maintient l’index actuel des sorties de tableaux triés. -
Jusqu’à ce que nous atteignions la fin du sous-tableau
arr[beg, .... ,mid]
ouarr[mid+1, .... ,end]
, nous prenons la plus petite valeur parmi les éléments de l’indexi
&j
et l’insérons dansoutput
. -
Choisissez les éléments restants et insérez-les dans
output
une fois qu’un des tableaux est épuisé. -
Copiez
output
dansarr[beg, ... , end]
.
Exemple de Timsort
Supposons que nous ayons le tableau : (3, 5, 2, 8, 1, 7, 6, 4)
. Nous allons le trier en utilisant l’algorithme de tri de Tim. Pour simplifier l’illustration, considérons que la taille de l’exécution est de 4
.
Divisez le tableau en deux sous-tableaux : (3, 5, 2, 8)
et (1, 7, 6, 4)
.
Le premier sous-tableau : (3, 5, 2, 8)
Sous-réseau trié | Sous-réseau non trié | Array |
---|---|---|
(3) | (5, 2, 8) | (3,5,2,8) |
- Premier tour
Clé : A[1]
= 5
Sous-réseau trié | Sous-réseau non trié | Array |
---|---|---|
( 3 , 5) | (2, 8) | (3, 5, 2, 8) |
- Deuxième tour
Clé : A[2]
= 4
Sous-réseau trié | Sous-réseau non trié | Array |
---|---|---|
( 2, 3, 5) | (8) | (2, 3, 5, 8) |
- Troisième tour
Clé : A[3]
= 2
Sous-réseau trié | Sous-réseau non trié | Array |
---|---|---|
( 2, 3, 5, 8) | () | (2, 3, 5, 8) |
Le deuxième sous-réseau : (1,7,6,4)
.
Sous-réseau trié | Sous-réseau non trié | Array |
---|---|---|
(1) | (7, 6, 4) | (1, 7, 6, 4) |
- Premier tour
Clé : A[1]
= 7
Sous-réseau trié | Sous-réseau non trié | Array |
---|---|---|
( 1 , 7) | (6, 4) | (1, 7, 6, 4) |
- Deuxième tour
Clé : A[2]
= 6
Sous-réseau trié | Sous-réseau non trié | Array |
---|---|---|
( 1, 6, 7) | (4) | (1, 6, 7, 4) |
- Troisième tour
Clé : A[3]
= 4
Sous-réseau trié | Sous-réseau non trié | Array |
---|---|---|
( 1, 4, 6, 7) | () | (1, 4, 6, 7) |
Fusionner les deux sous-réseaux triés pour obtenir le sous-réseau final en tant que : (1, 2, 3, 4, 5, 6, 7, 8)
Implémentation de l’algorithme Timsort
#include <bits/stdc++.h>
using namespace std;
const int RUN = 32;
void insertionSort(int arr[], int left, int right) {
for (int i = left + 1; i <= right; i++) {
int temp = arr[i];
int j = i - 1;
while (j >= left && arr[j] > temp) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = temp;
}
}
void merge(int arr[], int beg, int mid, int end) {
int output[end - beg + 1];
int i = beg, j = mid + 1, k = 0;
// add smaller of both elements to the output
while (i <= mid && j <= end) {
if (arr[i] <= arr[j]) {
output[k] = arr[i];
k += 1;
i += 1;
} else {
output[k] = arr[j];
k += 1;
j += 1;
}
}
// remaining elements from first array
while (i <= mid) {
output[k] = arr[i];
k += 1;
i += 1;
}
// remaining elements from the second array
while (j <= end) {
output[k] = arr[j];
k += 1;
j += 1;
}
// copy output to the original array
for (i = beg; i <= end; i += 1) {
arr[i] = output[i - beg];
}
}
void timSort(int arr[], int n) {
for (int i = 0; i < n; i += RUN)
insertionSort(arr, i, min((i + 31), (n - 1)));
for (int size = RUN; size < n; size = 2 * size) {
for (int left = 0; left < n; left += 2 * size) {
int mid = left + size - 1;
int right = min((left + 2 * size - 1), (n - 1));
merge(arr, left, mid, right);
}
}
}
int main() {
int n = 6;
int arr[6] = {5, 3, 4, 2, 1, 6};
cout << "Input array: ";
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
cout << "\n";
timSort(arr, n); // Sort elements in ascending order
cout << "Output array: ";
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
cout << "\n";
}
Complexité de l’algorithme de tri temporel
Complexité temporelle
- Cas moyen
L’algorithme nécessite des comparaisons O(nlogn)
pour trier un tableau de n
éléments. Par conséquent, la complexité temporelle est de l’ordre de [Big Theta] : O(nlogn)
.
- Pire cas
Dans le pire des cas, des comparaisons nlogn
sont nécessaires. La complexité temporelle dans le pire des cas est [Big O] : O(nlogn)
. C’est la même chose que la complexité temporelle moyenne.
- Meilleur cas
Dans le meilleur des cas, le tableau est déjà trié et aucun échange n’est nécessaire. Le meilleur cas de complexité temporelle est [Big Omega] : O(n)
.
Complexité spatiale
La complexité de l’espace pour cet algorithme est O(n)
parce que l’espace auxiliaire supplémentaire de O(n)
est requis par l’algorithme de tri par fusion.
Harshit Jindal has done his Bachelors in Computer Science Engineering(2021) from DTU. He has always been a problem solver and now turned that into his profession. Currently working at M365 Cloud Security team(Torus) on Cloud Security Services and Datacenter Buildout Automation.
LinkedIn