Algoritme voor emmersortering (Java, Python, C/C++ Code Voorbeelden)

⚡ Slimme samenvatting

Bij bucket sort worden de invoerelementen verdeeld over verschillende buckets, wordt elke bucket afzonderlijk gesorteerd en worden de resultaten vervolgens samengevoegd tot een gesorteerde eindtabel.

  • 🪣 Kernidee: Bij Bucket Sort worden waarden verdeeld over buckets, elke bucket wordt gesorteerd en vervolgens worden de resultaten in de juiste volgorde samengevoegd.
  • 📊 Beste pasvorm: Bucket Sort werkt het beste op gelijkmatig verdeelde drijvende-kommagetallen in [0.0, 1.0] of gelijkmatig verdeelde gehele getallen.
  • ⚡ Tijdscomplexiteit: Gemiddeld en in het beste geval bedraagt ​​de lineaire tijd O(n+k); in het slechtste geval daalt de tijd tot O(n²).
  • ✅ Voordelen: Buckets kunnen parallel worden verwerkt, wat geschikt is voor het extern sorteren van grote datasets.
  • 🧪 Implementatie: Code in C, C++, Pythonen Java Demonstreert zowel drijvende-komma- als gehele-komma-varianten.

Wat is bucketsortering?

Bucketsort, ook wel binsort genoemd, is een op vergelijkingen gebaseerde sorteermethode die een ongesorteerde array als invoer accepteert en een gesorteerde array als uitvoer produceert. Deze techniek verdeelt de elementen over verschillende buckets en sorteert elke bucket afzonderlijk met behulp van een ander sorteeralgoritme, zoals insertiesortering. Vervolgens worden alle buckets samengevoegd om de uiteindelijke gesorteerde array te vormen.

Bucket Sort wordt vaak gebruikt wanneer de elementen:

  1. Waarden met drijvende komma
  2. Gelijkmatig verdeeld over een bekend bereik

De tijdscomplexiteit van Bucket Sort hangt af van het aantal gebruikte buckets en de uniformiteit van de invoerverdeling. Terwijl andere sorteeralgoritmen zoals schelp soort, sorteer, heapsort en Snel sorteren Om in het beste geval een tijdcomplexiteit van O(n*logn) te bereiken, kan het Bucket Sort-algoritme onder gunstige omstandigheden een lineaire tijdcomplexiteit van O(n) bereiken.

Bucket Sort volgt de scatter-gather-methode. Elementen worden verspreid over de bijbehorende buckets, binnen elke bucket gesorteerd en in de laatste stap verzameld om een ​​gesorteerde array te vormen. Deze scatter-gather-methode wordt in de volgende sectie besproken.

Verspreidings- en verzamelbenadering

Grootschalige, complexe problemen kunnen soms lastig zijn om direct op te lossen. De scatter-gather-methode pakt dergelijke problemen aan door de gehele dataset in clusters te verdelen. Elk cluster wordt afzonderlijk verwerkt en de resultaten worden vervolgens weer samengevoegd om het uiteindelijke antwoord te verkrijgen.

Hieronder wordt uitgelegd hoe het Bucket Sort-algoritme de scatter-gather-methode implementeert:

Verspreidings- en verzamelbenadering

Hoe emmersortering werkt

Het basiswerkingsprincipe van Bucket Sort is als volgt:

  1. Er wordt een set lege emmers aangemaakt. Afhankelijk van het gekozen beleid kan het aantal emmers variëren.
  2. Elk element uit de invoerarray wordt in het bijbehorende vakje geplaatst.
  3. Elke emmer wordt afzonderlijk gesorteerd met behulp van een secundair sorteeralgoritme.
  4. De gesorteerde buckets worden samengevoegd tot één enkele uitvoerarray.

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

Methode 1: Bucket-sorteeralgoritme voor drijvende-komma Numbers

Het Bucket Sort-algoritme voor drijvende-komma getallen in het bereik [0.0, 1.0]:

Stap 1) Maak tien (10) lege emmers. De eerste emmer bevat getallen binnen het bereik [0.0, 0.1). De tweede emmer bevat [0.1, 0.2), enzovoort.

Stap 2) Voor elk array-element:

  • a. Bereken de bucketindex met behulp van de formule:
    bucket_index = aantal_buckets * array_element
  • b. Voeg het element in bucket[bucket_index] in.

Stap 3) Sorteer elke emmer afzonderlijk met behulp van invoegsortering.

Stap 4) Voeg alle buckets samen tot één gesorteerde array.

Laten we een voorbeeld van Bucket Sort bekijken. In dit voorbeeld sorteren we de volgende array:

Emmersorteeralgoritme voor drijvende-komma Numbers

Stap 1) Eerst maken we 10 lege emmers aan. De eerste emmer bevat getallen in het bereik [0.0, 0.1). De tweede emmer bevat getallen in het bereik [0.1, 0.2), enzovoort.

Emmersorteeralgoritme voor drijvende-komma Numbers

Stap 2) Bereken voor elk element in de array de bucket-index en plaats het element in die bucket.

De bucketindex wordt berekend met de volgende formule:
        bucket_index = aantal_buckets * array_element

Berekening van de bucketindex:
a) 0.78
      bucket_index = aantal_buckets * array_element
              = 10 * 0.78
              = 7.8
Daarom wordt het element 0.78 opgeslagen in bucket[floor(7.8)] of bucket[7].

Emmersorteeralgoritme voor drijvende-komma Numbers

b) 0.17
      bucket_index = aantal_buckets * array_element
              = 10 * 0.17
              = 1.7

Het array-element 0.17 wordt opgeslagen in bucket[floor(1.7)] of bucket[1].

Emmersorteeralgoritme voor drijvende-komma Numbers

c) 0.39
      bucket_index = aantal_buckets * array_element
              = 10 * 0.39
              = 3.9
0.39 wordt opgeslagen in bucket[floor(3.9)] of bucket[3].

Emmersorteeralgoritme voor drijvende-komma Numbers

Na het doorlopen van alle elementen in de array zien de buckets er als volgt uit:

Emmersorteeralgoritme voor drijvende-komma Numbers

Stap 3) Elke bucket wordt vervolgens gesorteerd met behulp van insertion sort. Na de sorteerbewerking is de uitvoer als volgt:

Emmersorteeralgoritme voor drijvende-komma Numbers

Stap 4) In de laatste stap worden de buckets samengevoegd tot één enkele array. Deze array is het gesorteerde resultaat van de invoer.

Elke bucket wordt aan de uitvoerarray toegevoegd. Bijvoorbeeld, de toevoeging van de elementen van de tweede bucket:

Emmersorteeralgoritme voor drijvende-komma Numbers

De samenvoeging van de laatste bucket-elementen wordt hieronder weergegeven:

Emmersorteeralgoritme voor drijvende-komma Numbers

Na het samenvoegen is de resulterende array de gewenste gesorteerde array.

Emmersorteeralgoritme voor drijvende-komma Numbers

Emmersorteerprogramma in C/C++

Input:

//Bucket Sort Program in C/C++
//For values without 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: 
";
  for (int i = 0; i< array_size; i++)
    cout<<input[i]<<" ";
  return 0;
}

Output:

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

Emmersorteerprogramma in Python

Input:

# Bucket Sort Program in Python
# For values without 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))

Output:

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

Emmer Sorteer in Java

Input:

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]+" ");
        }
    }
}

Output:

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

Methode 2: Bucket-sorteeralgoritme voor gehele elementen

Het Bucket Sort-algoritme voor invoer die getallen bevat buiten het bereik [0.0, 1.0] is iets anders dan het vorige. algoritmeDe stappen die in dit geval nodig zijn, zijn als volgt:

Stap 1) Zoek het maximum en het minimum element in de array.

Stap 2) Selecteer het aantal buckets, n, en initialiseer ze als leeg.

Stap 3) Bereken het bereik of de reikwijdte van elke bucket met behulp van de formule:
        span = (maximum - minimum) / n

Stap 4) Voor elk array-element:

  • 1. Bereken de bucketindex:
            bucket_index = (element - minimum) / span
  • 2. Voeg het element in bucket[bucket_index] in.

Stap 5) Sorteer elke emmer met behulp van invoegsortering.

Stap 6) Voeg alle buckets samen in één array.

Laten we een voorbeeld van dit Bucket Sort-algoritme bekijken. Voor dit voorbeeld sorteren we de volgende array:

Emmersorteeralgoritme voor gehele elementen

Stap 1) In de eerste stap bepalen we het maximum en het minimum van de gegeven array. In dit voorbeeld is het maximum 24 en het minimum 1.

Stap 2) Vervolgens kiezen we het aantal lege emmers, n. In dit voorbeeld gebruiken we 5 emmers en initialiseren we ze als leeg.

Stap 3) De omvang van elke emmer wordt berekend met behulp van de volgende formule:
        span = (maximum - minimum) / n = (24 - 1) / 5 = 4

De eerste emmer bevat dus getallen tussen [0, 5). De tweede emmer bevat [5, 10), enzovoort.

Emmersorteeralgoritme voor gehele elementen

Stap 4) Bereken voor elk element in de array de bucket-index en plaats het element in die bucket. De bucket-index wordt berekend met de volgende formule:
        bucket_index = (element - minimum) / span

Berekening van de bucketindex:

a) 11
bucket_index = (element – ​​minimum) / span
        = (11 - 1) / 4
        = 2

Element 11 wordt dus opgeslagen in bucket[2].

Emmersorteeralgoritme voor gehele elementen

b) 9
bucket_index = (element – ​​minimum) / span
        = (9 - 1) / 4
        = 2

Let op: Omdat 9 een grenselement is voor bucket[1], wordt het aan bucket[1] toegevoegd in plaats van in dezelfde bucket te worden geplaatst als het vorige element.

Emmersorteeralgoritme voor gehele elementen

Na het uitvoeren van de bewerkingen voor elk element zien de buckets er als volgt uit:

Emmersorteeralgoritme voor gehele elementen

Stap 5) Nu wordt elke bucket gesorteerd met behulp van insertion sort. De buckets na het sorteren:

Emmersorteeralgoritme voor gehele elementen

Stap 6) In de laatste stap worden de buckets samengevoegd tot één enkele array. reeks is het gesorteerde resultaat van de invoer.

Emmersorteeralgoritme voor gehele elementen

Emmersorteerprogramma in C/C++

Input:

#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=0; i < input.size(); i++)
    cout <<input[i]<<" ";
  return 0;
}

Output:

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

Emmersorteerprogramma in Python

Input:

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:
", input)

Output:

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

Emmer Sorteer in Java

Input:

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 + " ");
        }
    }
}

Output:

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

Voordelen en nadelen van de emmersorteermethode

VOORDELEN NADELEN
Voert snellere berekeningen uit op gelijkmatig verdeelde gegevens. Verbruikt meer ruimte in vergelijking met sorteeralgoritmen die de gegevens ter plaatse sorteren.
Kan worden gebruikt als externe sorteermethode voor grote datasets. Presteert slecht als de gegevens niet uniform zijn verdeeld
Buckets kunnen onafhankelijk en parallel worden verwerkt. Vereist voorafgaande kennis van het gegevensbereik en de gegevensverdeling.

Complexiteitsanalyse van bucketsortering

Bucket Sorteertijdcomplexiteit

  • Beste geval complexiteit: Als alle elementen van de array gelijkmatig verdeeld en vooraf gesorteerd zijn binnen elke bucket, kost het O(n) tijd om de elementen over de corresponderende buckets te verdelen. Vervolgens wordt elke bucket gesorteerd met behulp van invoegsoort De kosten bedragen O(k). De totale complexiteit is dus O(n+k).
  • Gemiddelde casuscomplexiteit: In gemiddelde gevallen gaan we ervan uit dat de invoer gelijkmatig verdeeld is. Het Bucket Sort-algoritme bereikt daardoor een lineaire tijdscomplexiteit van O(n+k). Hierbij is O(n) tijd nodig voor het verspreiden van de elementen en O(k) tijd voor het sorteren ervan met behulp van insertion sort.
  • Complexiteit in het ergste geval: In het ergste geval zijn de elementen niet gelijkmatig verdeeld en concentreren ze zich in één of twee emmers. In dat geval gedraagt ​​Bucket Sort zich vergelijkbaar met een bubbelsorteeralgoritmeDaarom is de tijdscomplexiteit van Bucket Sort in het slechtste geval O(n²).

Ruimtecomplexiteit van emmersortering

De ruimtecomplexiteit van Bucket Sort is O(n*k). Hierbij is n het aantal elementen en k het aantal emmers dat nodig is om ze tijdens het sorteren op te slaan.

Veelgestelde vragen

Gebruik Bucket Sort wanneer de invoerwaarden gelijkmatig verdeeld zijn over een bekend bereik, met name drijvende-komma getallen in [0.0, 1.0]. Het levert lineaire tijd op voor dergelijke gegevens, maar presteert slecht bij geclusterde of onbekende verdelingen.

Bucket Sort is stabiel wanneer het interne sorteeralgoritme dat binnen elke bucket wordt gebruikt stabiel is. Insertion Sort behoudt de relatieve volgorde van gelijke elementen, dus de standaardimplementatie van Bucket Sort met insertion sort wordt als stabiel beschouwd.

Bucket Sort groepeert elementen op basis van een waardebereik en sorteert elke bucket met een ander algoritme. Radix Sort groepeert getallen cijfer voor cijfer en gebruikt intern een telmethode. Bucket Sort heeft een voorkeur voor gelijkmatig verdeelde drijvende-kommagetallen; Radix Sort heeft een voorkeur voor gehele getallen met een vaste breedte of tekenreeksen.

De tijdcomplexiteit van Bucket Sort in het slechtste geval is O(n²). Dit treedt op wanneer alle invoerelementen in één enkele emmer terechtkomen, waardoor de interne sorteerbewerking (meestal insertion sort) zich kwadratisch gedraagt. Uniforme verdeling voorkomt dit scenario.

Ja. Om negatieve waarden te verwerken, zoek je eerst het minimum en het maximum en bereken je vervolgens de bucketindex met (element – ​​minimum) / bereik. Hierdoor worden negatieve waarden naar een niet-negatieve indexruimte verplaatst en kan de standaard Bucket Sort-logica ongewijzigd verdergaan.

AI-gestuurde platforms zoals VisuAlgo, Algorithm Visualizer en ChatGPT genereerden stapsgewijze instructies. tracDe animaties helpen leerlingen Bucket Sort te visualiseren. Ze laten de fasen van verspreiden, sorteren en verzamelen zien, waardoor de wiskunde achter de emmerindex en de logica van de verdeling gemakkelijker te begrijpen zijn.

Door AI aangedreven aanbevelingssystemen analyseren de grootte van de dataset, de waardeverdeling en de geheugenlimieten om een ​​passend algoritme voor te stellen. Voor gelijkmatig verdeelde drijvende-kommagetallen geven dergelijke systemen de voorkeur aan Bucket Sort. Voor gemengde gehele getallenreeksen kunnen ze in plaats daarvan Quicksort of Radix Sort voorstellen.

Vat dit bericht samen met: