Algorithme de tri de seau (Java, Python, C /C++ Exemples de codes)

Quโ€™est-ce que le tri par seau ?

Le tri par compartiment, souvent appelรฉ tri par bac, est une mรฉthode de tri par comparaison qui accepte un tableau non triรฉ comme entrรฉe et produit en consรฉquence un tableau triรฉ. Cette mรฉthode fonctionne en distribuant les รฉlรฉments dans plusieurs compartiments et en triant chacun de ces compartiments individuellement par n'importe quel algorithme de tri tel que le tri par insertion. Ensuite, tous les compartiments sont fusionnรฉs pour former un tableau triรฉ.

Le tri par compartiment est couramment utilisรฉ lorsque les รฉlรฉments sont :

  1. Valeurs ร  virgule flottante
  2. Uniformรฉment rรฉparti sur une plage

La complexitรฉ temporelle du tri par compartiments dรฉpend du nombre de compartiments utilisรฉs et de l'uniformitรฉ de la distribution des entrรฉes. Alors que diffรฉrents algorithmes de tri tels que sorte de coquille, fusionner le tri, le tri en tas et tri rapide peut atteindre la complexitรฉ temporelle dans le meilleur des cas de O(n*logn), l'algorithme de tri par compartiments peut atteindre la mรชme complexitรฉ temporelle linรฉaire ou O(n).

Le tri par compartiment suit l'approche scatter-gather. En appliquant cette approche, les รฉlรฉments sont dispersรฉs dans les compartiments correspondants, triรฉs dans les compartiments et rassemblรฉs pour former un tableau triรฉ lors de l'รฉtape finale. Cette approche scatter-gather est discutรฉe dans la section suivante

Approche Dispersion-Rassemblement

Des problรจmes complexes et ร  grande รฉchelle peuvent parfois รชtre difficiles ร  rรฉsoudre. L'approche scatter-gather tente de rรฉsoudre de tels problรจmes en divisant l'ensemble des donnรฉes en clusters. Ensuite, chaque cluster est abordรฉ sรฉparรฉment et le tout rassemblรฉ pour obtenir la rรฉponse finale.

Voici comment l'algorithme de tri par bucket implรฉmente la mรฉthode scatter-gather :

Approche Dispersion-Rassemblement

Comment fonctionne le tri par compartiment

Le principe de fonctionnement de base du tri par compartiments est le suivant :

  1. Un ensemble de compartiments vides est crรฉรฉ. En fonction des diffรฉrentes politiques, le nombre de compartiments peut diffรฉrer.
  2. ร€ partir du tableau d'entrรฉe, placez chaque รฉlรฉment dans son compartiment correspondant.
  3. Triez ces compartiments individuellement.
  4. Concatรฉnez les compartiments triรฉs pour crรฉer un seul tableau de sortie.

Les รฉtapes de travail dรฉtaillรฉes sont fournies dans les sections suivantes.

Pseudo code

Start
Create N empty buckets
For each array element:
Calculate bucket index
Put that element into the corresponding bucket
For each bucket:
Sort elements within each bucket
Merge all the elements from each bucket
Output the sorted array
End

Mรฉthode 1 : algorithme de tri par compartiment pour la virgule flottante Numbers

L'algorithme de tri par compartiment pour les nombres ร  virgule flottante compris entre 0.0 et 1.0 :

ร‰tape 1) Crรฉez dix (10) compartiments vides de telle sorte que le premier compartiment contienne des nombres compris dans la plage [0.0, 0.1). Ensuite, le deuxiรจme compartiment contiendra [0.1, 0.2), et ainsi de suite.

ร‰tape 2) Pour chaque รฉlรฉment du tableau :

      un. Calculez l'indice de compartiment ร  l'aide de la formule :
      index du compartiment = no_of_buckets *array_element
      b. Insรฉrez l'รฉlรฉment dans le bucket[bucket_index]

ร‰tape 3) Triez chaque compartiment individuellement ร  lโ€™aide du tri par insertion.

ร‰tape 4) Concatรฉnez tous les compartiments dans un seul tableau.

Voyons un exemple de tri par bucket. Pour cet exemple, nous allons trier le tableau suivant ร  l'aide de l'algorithme de tri par compartiment :

Algorithme de tri par compartiment pour virgule flottante Numbers

ร‰tape 1) Tout dโ€™abord, nous allons crรฉer 10 buckets vides. Le premier compartiment contiendra les nombres compris entre [0.0, 0.1). Ensuite, le deuxiรจme compartiment contiendra les nombres compris entre [0.1, 0.2) et ainsi de suite.

Algorithme de tri par compartiment pour virgule flottante Numbers

ร‰tape 2) Pour chaque รฉlรฉment du tableau, nous calculerons lโ€™index du bucket et placerons lโ€™รฉlรฉment dans ce bucket.

L'indice de compartiment peut รชtre calculรฉ ร  l'aide de la formule :
              bucket_index= no_of_buckets*array_element

Calcul de l'indice de compartiment :
a) 0.78
      bucket_index = no_of_buckets*array_element
                   = 10 * 0.78
                   = 7.8
Par consรฉquent, l'รฉlรฉment 0.78 sera stockรฉ sur le bucket[floor(7.8)] ou le bucket[7].

Algorithme de tri par compartiment pour virgule flottante Numbers

b) 0.17
      bucket_index = no_of_buckets * รฉlรฉment du tableau
                   = 10 * 0.17
                   = 1.7

L'รฉlรฉment de tableau 0.17 sera stockรฉ sur bucket[floor(1.7)] ou bucket[1].

Algorithme de tri par compartiment pour virgule flottante Numbers

c) 0.39
      bucket_index = no_of_buckets * รฉlรฉment du tableau
                   = 10 * 0.39
                   = 3.9
   0.39 sera stockรฉ sur bucket[floor(3.9)] ou bucket[3].

Algorithme de tri par compartiment pour virgule flottante Numbers

Aprรจs avoir parcouru tous les รฉlรฉments du tableau, les buckets seront les suivants :

Algorithme de tri par compartiment pour virgule flottante Numbers

ร‰tape 3) Ensuite, chaque compartiment sera triรฉ ร  lโ€™aide du tri par insertion. Aprรจs l'opรฉration de tri, le rรฉsultat serait :

Algorithme de tri par compartiment pour virgule flottante Numbers

ร‰tape 4) Dans la derniรจre รฉtape, les buckets seront concatรฉnรฉs en un seul tableau. Ce tableau sera le rรฉsultat triรฉ de lโ€™entrรฉe.

Chaque bucket sera concatรฉnรฉ au tableau de sortie. Par exemple, la concatรฉnation des รฉlรฉments du deuxiรจme bucket :

Algorithme de tri par compartiment pour virgule flottante Numbers

La concatรฉnation des derniers รฉlรฉments du bucket sera la suivante :

Algorithme de tri par compartiment pour virgule flottante Numbers

Aprรจs concatรฉnation, le tableau rรฉsultant sera le tableau triรฉ souhaitรฉ.

Algorithme de tri par compartiment pour virgule flottante Numbers

Programme de tri de seaux en C/C++

Entrรฉes :

//Bucket Sort Program in C/C++
//For not having integer parts
#include <bits/stdc++.h>
#define BUCKET_SIZE 10
using namespace std;
void bucketSort(float input[], int array_size)
{
  vector <float>bucket[BUCKET_SIZE];
for (int i = 0; i < array_size; i++) {
    int index = BUCKET_SIZE*input[i];
 bucket[index].push_back(input[i]);
  }
for (int i = 0; i < BUCKET_SIZE; i++)
    sort(bucket[i].begin(), bucket[i].end());
  int out_index = 0;
  for (int i = 0; i < BUCKET_SIZE; i++)
    for (int j = 0; j < bucket[i].size(); j++)
      input[out_index++] = bucket[i][j];
}
int main()
{
float input[]={0.78,0.17,0.39,0.26,0.72,0.94,0.21,0.12,0.23,0.69};
 int array_size = sizeof(input)/sizeof(input[0]);
 
 bucketSort(input, array_size);
 cout <<"Sorted Output: \n";
 for (int i = 0; i< array_size; i++)
 cout<<input[i]<<" ";
return 0;
}

Sortie :

Sorted Output:
0.12 0.17 0.21 0.23 0.26 0.39 0.69 0.72 0.78 0.94

Programme de tri par seau dans Python

Entrรฉes :

# Bucket Sort Program in Python
# For not having integer parts
def bucketSort(input):
    output = []
    bucket_size = 10
    for bucket in range(bucket_size):
        output.append([])
    for element in input:
        index = int(bucket_size * element)
        output[index].append(element)
    for bucket in range(bucket_size):
        output[bucket] = sorted(output[bucket])
    out_index = 0
    for bucket in range(bucket_size):
        for element in range(len(output[bucket])):
            input[out_index] = output[bucket][element]
            out_index += 1
    return input

input = [0.78, 0.17, 0.39, 0.26, 0.72, 0.94, 0.21, 0.12, 0.23, 0.69]
print("Sorted Output:")
print(bucketSort(input))

Sortie :

Sorted Output:
[0.12, 0.17, 0.21, 0.23, 0.26, 0.39, 0.69, 0.72, 0.78, 0.94]

Seau Trier dans Java

Entrรฉes :

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class BucketSort {
    private static final int BUCKET_SIZE = 10;
    public static void bucketSort(float[] input, int arraySize) {
        List <
        Float >
        [] bucket = new ArrayList[BUCKET_SIZE];
        for (int i = 0; i < arraySize; i++) {
            int index = (int)(BUCKET_SIZE * input[i]);
            if (bucket[index] == null) {
                bucket[index] = new ArrayList < >
                ();
            }
            bucket[index].add(input[i]);
        }
        for (int i = 0; i < BUCKET_SIZE; i++) {
            if (bucket[i] != null) {
                Collections.sort(bucket[i]);
            }
        }
        int outIndex = 0;
        for (int i = 0; i < BUCKET_SIZE; i++) {
            if (bucket[i] != null) {
                for (float value: bucket[i]) {
                    input[outIndex++] = value;
               }
            }
        }
    }
    public static void main(String[] args) {
    float[] input = {0.78f,0.17f,0.39f,0.26f,0.72f,0.94f,0.21f,0.12f,0.23f,0.69f};
        int arraySize = input.length;
        bucketSort(input, arraySize);
        System.out.println("Sorted Output:");
        for (int i = 0; i < arraySize; i++) {
            System.out.print(input[i]+" ");
        }
    }
}

Sortie :

Sorted Output:
0.12 0.17 0.21 0.23 0.26 0.39 0.69 0.72 0.78 0.94

Mรฉthode 2 : algorithme de tri par compartiment pour les รฉlรฉments entiers

L'algorithme de tri par compartiment pour l'entrรฉe contenant des nombres au-delร  de la plage [0.0, 1.0] est un peu diffรฉrent du prรฉcรฉdent. algorithme. Les รฉtapes requises pour ce cas sont les suivantes :

ร‰tape 1) Trouvez les รฉlรฉments maximum et minimum.

ร‰tape 2) Sรฉlectionnez le nombre de compartiments, n, et initialisez ces compartiments comme รฉtant vides.

ร‰tape 3) Calculez la plage ou la portรฉe de chaque compartiment ร  l'aide de la formule :
               span = (maximum - minimum)/n

ร‰tape 4) Pour chaque รฉlรฉment du tableau :

    1.Calculer l'indice du bucket :
                   bucket_index = (element - minimum)/span
    2.Insรฉrez l'รฉlรฉment dans le bucket[bucket_index]

ร‰tape 5) Triez chaque compartiment ร  lโ€™aide du tri par insertion.

ร‰tape 6) Concatรฉnez tous les compartiments dans un seul tableau.

Voyons un exemple de cet algorithme de tri par compartiment. Pour cet exemple, nous allons trier le tableau suivant ร  l'aide de l'algorithme de tri par compartiment :

Algorithme de tri par compartiment pour les รฉlรฉments entiers

ร‰tape 1) Dans la premiรจre รฉtape, les รฉlรฉments maximum et minimum du tableau donnรฉ doivent รชtre trouvรฉs. Pour cet exemple, le maximum est 24 et le minimum est 1.

ร‰tape 2) Maintenant, nous devons sรฉlectionner un nombre de compartiments vides, n. Dans cet exemple, nous prendrons 5 seaux. Ensuite nous les initialiserons comme vides.

ร‰tape 3) La portรฉe de chaque compartiment doit รชtre calculรฉe ร  l'aide de la formule suivante :
               span = (maximum-minimum)/n = (24-1)/5 = 4;

Par consรฉquent, le premier compartiment contiendra les nombres compris dans la plage [0, 5). Le deuxiรจme compartiment contiendra les nombres compris entre [5, 10) et ainsi de suite.

Algorithme de tri par compartiment pour les รฉlรฉments entiers

ร‰tape 4) Pour chaque รฉlรฉment du tableau, nous calculerons lโ€™index du bucket et placerons lโ€™รฉlรฉment dans ce bucket. L'indice de compartiment peut รชtre calculรฉ ร  l'aide de la formule :
               bucket_index = (element - minimum)/span

Calcul de l'indice de compartiment :

    a) 11bucket_index = (รฉlรฉment โ€“ โ€‹โ€‹minimum)/span
                       =(11 1-4 )/
                       =2

Ainsi, l'รฉlรฉment 11 sera stockรฉ dans bucket[2].

Algorithme de tri par compartiment pour les รฉlรฉments entiers

    b) 9
    bucket_index = (รฉlรฉment โ€“ โ€‹โ€‹minimum)/span
                       =(9 1-4 )/
                       =2

Note: Comme 9 est un รฉlรฉment de limite pour le bucket[1], il doit รชtre ajoutรฉ dans bucket[1] au lieu d'รชtre ajoutรฉ dans le mรชme bucket de l'รฉlรฉment prรฉcรฉdent.

Algorithme de tri par compartiment pour les รฉlรฉments entiers

Aprรจs avoir effectuรฉ les opรฉrations pour chaque รฉlรฉment, les buckets seront les suivants :

Algorithme de tri par compartiment pour les รฉlรฉments entiers

ร‰tape 5) Dรฉsormais, chaque compartiment sera triรฉ ร  lโ€™aide du tri par insertion. Les seaux aprรจs tri-

Algorithme de tri par compartiment pour les รฉlรฉments entiers

ร‰tape 6) Dans la derniรจre รฉtape, les buckets seront concatรฉnรฉs en un seul tableau. Que tableau sera le rรฉsultat triรฉ de lโ€™entrรฉe.

Algorithme de tri par compartiment pour les รฉlรฉments entiers

Programme de tri de seaux en C/C++

Entrรฉes :

#include<bits/stdc++.h>
using namespace std;
void bucketSort(vector < double > & input, int No_Of_Buckets)
{
  double max_value = * max_element(input.begin(), input.end());
  double min_value = * min_element(input.begin(), input.end());
  double span = (max_value - min_value) / No_Of_Buckets;
  vector<vector <double>>
  output;
  for (int i = 0; i < No_Of_Buckets; i++)
    output.push_back(vector <double>
      ());
  for (int i = 0; i < input.size(); i++)
  {
    double difference = (input[i] - min_value) / span
     -
      int((input[i] - min_value) / span);
    if (difference == 0 && input[i] != min_value)
      output[int((input[i] - min_value) / span) - 1]
      .push_back(input[i]);
    else
      output[int((input[i] - min_value) / span)].push_back(
        input[i]);
  }
  for (int i = 0; i < output.size(); i++)
  {
    if (!output[i].empty())
      sort(output[i].begin(), output[i].end());
  }
  int index = 0;
  for (vector <double> & bucket: output)
  {
    if (!bucket.empty())
    {
      for (double i: bucket)
      {
        input[index] = i;
        index++;
      }
    }
  }
}
int main()
{
  vector <double>
  input ={11,9,21,8,17,19,13,1,24,12
  };
  int No_Of_Buckets = 5;
  bucketSort(input, No_Of_Buckets);
  cout<<
  "Sorted Output:";
  for (int i; i < input.size(); i++)
    cout <<input[i]<<" ";
  return 0;
}

Sortie :

Sorted Output:1 8 9 11 12 13 17 19 21 24

Programme de tri par seau dans Python

Entrรฉes :

def bucketSort(input, No_Of_Buckets):
    max_element = max(input)
    min_element = min(input)
    span = (max_element - min_element) / No_Of_Buckets
    output = []
    for bucket in range(No_Of_Buckets):
        output.append([])
    for element in range(len(input)):
        diff = (input[element] - min_element) / span - int(
            (input[element] - min_element) / span
        )
        if diff == 0 and input[element] != min_element:
            output[int((input[element] - min_element) / span) - 1].append(
                input[element]
            )
        else:
            output[int((input[element] - min_element) / span)].append(input[element])
    for bucket in range(len(output)):
        if len(output[bucket]) != 0:
            output[bucket].sort()
    index = 0
    for bucket in output:
        if bucket:
            for element in bucket:
                input[index] = element
                index = index + 1
input = [11, 9, 21, 8, 17, 19, 13, 1, 24, 12]
No_Of_Buckets = 5
bucketSort(input, No_Of_Buckets)
print("Sorted Output:\n", input)

Sortie :

Sorted Output:
[1, 8, 9, 11, 12, 13, 17, 19, 21, 24]

Seau Trier dans Java

Entrรฉes :

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class BucketSort {
    public static void bucketSort(List < Double > input, int No_Of_Buckets) {
        double max_value = Collections.max(input);
        double min_value = Collections.min(input);
        double span =(max_value - min_value) / No_Of_Buckets;
        List <
        List <
        Double > >
        output = new ArrayList < >
        ();
        for (int i = 0; i < No_Of_Buckets; i++) {
            output.add(new ArrayList < >
                ());
        }
        for (Double value: input) {
            double difference = (value - min_value) / span - ((value - min_value) / span);
            if (difference == 0 && value != min_value) {
                output.get((int)((value - min_value) / span) - 1).add(value);
            } else {
                output.get((int)((value - min_value) / span)).add(value);
				}
			}
        for (List <Double> bucket: output) {
            if (!bucket.isEmpty()) {
			Collections.sort(bucket);
            }
        }
        int index = 0;
        for (List <Double> bucket: output) {
            if (!bucket.isEmpty()) {
                for (Double value: bucket) {
                    input.set(index,value);
                    index++;
                }
            }
        }
    }
    public static void main(String[] args) {
        List <Double>
        input = new ArrayList <>
        ();
        input.add(11.0);
		input.add(9.0);
        input.add(21.0);
        input.add(8.0);
        input.add(17.0);
        input.add(19.0);
        input.add(13.0);
        input.add(1.0);
        input.add(24.0);
        input.add(12.0);
        int No_Of_Buckets = 5;
        bucketSort(input, No_Of_Buckets);
        System.out.println("Sorted Output:");
        for (Double value: input) {
		System.out.print(value + " ");
        }
    }
}

Sortie :

Sorted Output:
1.0 8.0 9.0 11.0 12.0 13.0 17.0 19.0 21.0 24.0

Avantages et inconvรฉnients

Avantages Inconvรฉnients
Effectuer un calcul plus rapide Consomme plus d'espace par rapport aux autres algorithmes
Il peut รชtre utilisรฉ comme mรฉthode de tri externe Fonctionne mal lorsque les donnรฉes ne sont pas uniformรฉment rรฉparties
Les seaux peuvent รชtre traitรฉs indรฉpendamment

Analyse de la complexitรฉ du tri par compartiment

Complexitรฉ temporelle du tri par seau

  • Meilleur cas de complexitรฉ :Si tous les รฉlรฉments du tableau sont uniformรฉment distribuรฉs et triรฉs au prรฉalable, il faudrait un temps O(n) pour disperser les รฉlรฉments dans les compartiments correspondants. Triez ensuite chaque seau en utilisant tri par insertion coรปterait O(k). Ainsi, la complexitรฉ globale serait O(n+k).
  • Complexitรฉ moyenne des cas :Pour les cas moyens, nous supposons que les entrรฉes sont uniformรฉment distribuรฉes. Ainsi, l'algorithme de tri par compartiment atteint une complexitรฉ temporelle linรฉaire de O (n + k). Ici, un temps O(n) est nรฉcessaire pour disperser les รฉlรฉments et un temps O(k) est nรฉcessaire pour trier ces รฉlรฉments ร  l'aide du tri par insertion.
  • Pire complexitรฉ des cas :Dans le pire des cas, les รฉlรฉments ne seront pas uniformรฉment rรฉpartis et concentrรฉs sur un ou deux seaux spรฉcifiques. Dans ce cas, le tri par compartiment fonctionnera comme un algorithme de tri ร  bulles. Par consรฉquent, dans le pire des cas, la complexitรฉ temporelle dโ€™un tri par compartiment serait O(n^2).

Complexitรฉ spatiale du tri par seau

La complexitรฉ spatiale du tri par compartiment est O(n*k). Ici n est le nombre d'รฉlรฉments et k est le nombre de compartiments requis.

Rรฉsumez cet article avec :