Algoritam za sortiranje spremnika (Java, Python, C/C++ Code Primjeri)

โšก Pametni saลพetak

Bucket sortiranje rasprลกuje ulazne elemente u nekoliko bucketa, sortira svaki bucket neovisno i okuplja ih kako bi se dobio konaฤni sortirani niz.

  • ๐Ÿชฃ Osnovna ideja: Sortiranje po skupinama dijeli vrijednosti po skupinama, sortira svaku od njih, a zatim ih spaja po redu.
  • ๐Ÿ“Š Najbolje odgovara: Bucket sort najbolje funkcionira na jednoliko rasporeฤ‘enim float brojevima u [0.0, 1.0] ili jednoliko rasporeฤ‘enim cijelim brojevima.
  • โšก Sloลพenost vremena: Prosjeฤni i najbolji sluฤajevi doseลพu linearno vrijeme O(n+k); najgori sluฤaj degradira na O(nยฒ).
  • โœ… Prednosti: Kante se mogu obraฤ‘ivati โ€‹โ€‹paralelno, ลกto je pogodno za vanjsko sortiranje velikih skupova podataka.
  • ๐Ÿงช provedba: Code u C-u, C++, Pythoni Java prikazuje i varijante s pomiฤnim zarezom i cjelobrojne varijante.

ล to je Bucket Sort?

Sortiranje po skupinama, ฤesto nazivano sortiranje po skupinama, metoda je sortiranja distribucijom temeljena na usporedbi koja prihvaฤ‡a nesortirani niz kao ulaz, a kao izlaz proizvodi sortirani niz. Ova tehnika distribuira elemente u nekoliko skupina i sortira svaku skupinu pojedinaฤno pomoฤ‡u drugog algoritma sortiranja, kao ลกto je sortiranje umetanjem. Zatim se sve skupine spajaju kako bi se formirao konaฤni sortirani niz.

Bucket sort se obiฤno koristi kada su elementi:

  1. Vrijednosti s pomiฤnim zarezom
  2. Ravnomjerno rasporeฤ‘eno po poznatom rasponu

Vremenska sloลพenost sortiranja po skupinama ovisi o broju koriลกtenih skupina i ujednaฤenosti distribucije ulaznih podataka. Dok drugi algoritmi sortiranja, kao ลกto su sortirati ลกkoljke, sortiranje spajanjem, heapsortiranje i ลพiva sorta postiฤ‡i vremensku sloลพenost u najboljem sluฤaju od O(n*logn), algoritam Bucket Sort moลพe postiฤ‡i linearnu vremensku sloลพenost O(n) pod povoljnim uvjetima.

Sortiranje po skupinama slijedi pristup rasprลกenja i sakupljanja. Elementi se rasprลกuju u odgovarajuฤ‡e skupine, sortiraju unutar svake skupine i skupljaju u sortirani niz kao posljednji korak. Ovaj pristup rasprลกenja i sakupljanja raspravlja se u sljedeฤ‡em odjeljku.

Pristup rasprลกivanja i sakupljanja

Veliki, sloลพeni problemi ponekad mogu biti izazovni za izravno rjeลกavanje. Pristup rasprลกenja i prikupljanja rjeลกava takve probleme dijeljenjem cijelog skupa podataka u klastere. Svaki klaster se obraฤ‘uje zasebno, a rezultati se ponovno spajaju kako bi se dobio konaฤni odgovor.

Evo kako algoritam Bucket Sort implementira metodu rasprลกenja i sakupljanja:

Pristup rasprลกivanja i sakupljanja

Kako radi Bucket Sort

Osnovni princip rada Bucket sortiranja je sljedeฤ‡i:

  1. Izraฤ‘uje se skup praznih spremnika. Broj spremnika moลพe varirati ovisno o odabranoj politici.
  2. Iz ulaznog niza, svaki element se smjeลกta u odgovarajuฤ‡u skupinu.
  3. Svaka se skupina sortira pojedinaฤno pomoฤ‡u sekundarnog algoritma sortiranja.
  4. Sortirane kante se spajaju kako bi se dobio jedan izlazni niz.

Nadimak 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

Metoda 1: Algoritam za sortiranje u segmentu za pokretni zarez Numbers

Algoritam Bucket Sort za brojeve s pomiฤnim zarezom unutar raspona [0.0, 1.0]:

Korak 1) Napravite deset (10) praznih kanti. Prva kanta sadrลพi brojeve unutar raspona [0.0, 0.1]. Druga kanta sadrลพi [0.1, 0.2) i tako dalje.

Korak 2) Za svaki element niza:

  • a. Izraฤunajte indeks skupine pomoฤ‡u formule:
    indeks_kategorije = broj_kategorija * element_arraya
  • b. Umetnite element u kantu[bucket_index]

Korak 3) Razvrstajte svaku kantu zasebno pomoฤ‡u sortiranja umetanjem.

Korak 4) Spojite sve kontejnere u jedan sortirani niz.

Proฤ‘imo kroz primjer sortiranja pomoฤ‡u bucketa. U ovom primjeru sortirat ฤ‡emo sljedeฤ‡i niz:

Algoritam bucket sortiranja za pokretni zarez Numbers

Korak 1) Prvo stvaramo 10 praznih kanti. Prva kanta sadrลพi brojeve u [0.0, 0.1]. Druga kanta sadrลพi [0.1, 0.2) i tako dalje.

Algoritam bucket sortiranja za pokretni zarez Numbers

Korak 2) Za svaki element niza izraฤunajte indeks segmenta i smjestite element u taj segment.

Indeks koลกarice izraฤunava se pomoฤ‡u formule:
        indeks_kategorije = broj_kategorija * element_arraya

Izraฤun skupnog indeksa:
a) 0.78
      indeks_kategorije = broj_kategorija * element_arraya
              = 10 * 0.78
              = 7.8
Dakle, element 0.78 pohranjen je u bucket[floor(7.8)] ili bucket[7].

Algoritam bucket sortiranja za pokretni zarez Numbers

b) 0.17
      indeks_kategorije = broj_kategorija * element_arraya
              = 10 * 0.17
              = 1.7

Element polja 0.17 pohranjen je u bucket[floor(1.7)] ili bucket[1].

Algoritam bucket sortiranja za pokretni zarez Numbers

c) 0.39
      indeks_kategorije = broj_kategorija * element_arraya
              = 10 * 0.39
              = 3.9
0.39 se pohranjuje u bucket[floor(3.9)] ili bucket[3].

Algoritam bucket sortiranja za pokretni zarez Numbers

Nakon iteracije kroz sve elemente niza, kontejneri izgledaju ovako:

Algoritam bucket sortiranja za pokretni zarez Numbers

Korak 3) Svaka se sekcija zatim sortira pomoฤ‡u sortiranja umetanjem. Nakon operacije sortiranja, izlaz je:

Algoritam bucket sortiranja za pokretni zarez Numbers

Korak 4) U zavrลกnom koraku, segmenti se spajaju u jedan niz. Taj niz je sortirani rezultat ulaza.

Svaka sekcija je spojena s izlaznim nizom. Na primjer, spajanje elemenata druge sekcija:

Algoritam bucket sortiranja za pokretni zarez Numbers

Spajanje elemenata posljednjeg kontejnera prikazano je u nastavku:

Algoritam bucket sortiranja za pokretni zarez Numbers

Nakon spajanja, rezultirajuฤ‡i niz je ลพeljeni sortirani niz.

Algoritam bucket sortiranja za pokretni zarez Numbers

Program za sortiranje spremnika u C/C++

Ulazni:

//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;
}

Izlaz:

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

Bucket Sort Program in Python

Ulazni:

# 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))

Izlaz:

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

Kanta Sortiraj u Java

Ulazni:

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

Izlaz:

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

Metoda 2: algoritam sortiranja u segmentu za cjelobrojne elemente

Algoritam sortiranja po skupinama za unos koji sadrลพi brojeve izvan raspona [0.0, 1.0] malo se razlikuje od prethodnog. algoritamKoraci potrebni za ovaj sluฤaj su sljedeฤ‡i:

Korak 1) Pronaฤ‘ite maksimalni i minimalni broj elemenata u nizu.

Korak 2) Odaberite broj kontejnera, n, i inicijalizirajte ih kao prazne.

Korak 3) Izraฤunajte raspon ili raspon svake kante pomoฤ‡u formule:
        span = (maximum - minimum) / n

Korak 4) Za svaki element niza:

  • 1. Izraฤunajte indeks koลกarice:
            bucket_index = (element - minimum) / span
  • 2. Umetnite element u kantu[bucket_index]

Korak 5) Razvrstaj svaku kantu pomoฤ‡u sortiranja umetanjem.

Korak 6) Spojite sve kante u jedno polje.

Pogledajmo primjer ovog algoritma Bucket Sort. Za ovaj primjer sortirat ฤ‡emo sljedeฤ‡i niz:

Algoritam za razvrstavanje spremnika za cjelobrojne elemente

Korak 1) U prvom koraku pronalazimo maksimalni i minimalni broj elemenata zadanog niza. Za ovaj primjer, maksimalni broj je 24, a minimalni 1.

Korak 2) Zatim odabiremo broj praznih kanti, n. U ovom primjeru koristimo 5 kanti i inicijaliziramo ih kao prazne.

Korak 3) Raspon svake kante izraฤunava se pomoฤ‡u formule:
        span = (maximum - minimum) / n = (24 - 1) / 5 = 4

Dakle, prva kanta sadrลพi brojeve unutar [0, 5). Druga kanta sadrลพi [5, 10) i tako dalje.

Algoritam za razvrstavanje spremnika za cjelobrojne elemente

Korak 4) Za svaki element polja izraฤunajte indeks segmenta i smjestite element u taj segment. Indeks segmenta izraฤunava se pomoฤ‡u formule:
        bucket_index = (element - minimum) / span

Izraฤun skupnog indeksa:

a) 11
bucket_index = (element โ€“ โ€‹โ€‹minimum) / raspon
        = (11 โ€“ 1) / 4
        = 2

Dakle, element 11 je pohranjen u spremniku[2].

Algoritam za razvrstavanje spremnika za cjelobrojne elemente

b) 9
bucket_index = (element โ€“ โ€‹โ€‹minimum) / raspon
        = (9 โ€“ 1) / 4
        = 2

Biljeลกka: Buduฤ‡i da je 9 graniฤni element za bucket[1], dodaje se bucket[1] umjesto da bude smjeลกten u isti bucket kao i prethodni element.

Algoritam za razvrstavanje spremnika za cjelobrojne elemente

Nakon izvoฤ‘enja operacija za svaki element, kante izgledaju kako slijedi:

Algoritam za razvrstavanje spremnika za cjelobrojne elemente

Korak 5) Sada je svaka kanta sortirana pomoฤ‡u sortiranja umetanjem. Kante nakon sortiranja:

Algoritam za razvrstavanje spremnika za cjelobrojne elemente

Korak 6) U zavrลกnom koraku, kante se spajaju u jedan niz. To poredak je sortirani ishod ulaza.

Algoritam za razvrstavanje spremnika za cjelobrojne elemente

Program za sortiranje spremnika u C/C++

Ulazni:

#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;
}

Izlaz:

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

Bucket Sort Program in Python

Ulazni:

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)

Izlaz:

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

Kanta Sortiraj u Java

Ulazni:

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

Izlaz:

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

Prednosti i nedostaci sortiranja po bucketima

Prednosti Nedostaci
Brลพe izraฤunava na jednoliko rasporeฤ‘enim podacima Zauzima viลกe prostora u usporedbi s algoritmima za sortiranje na mjestu
Moลพe se koristiti kao vanjska metoda sortiranja za velike skupove podataka Loลกe radi kada podaci nisu ravnomjerno rasporeฤ‘eni
Kante se mogu obraฤ‘ivati โ€‹โ€‹neovisno i paralelno Zahtijeva unaprijed poznavanje raspona i distribucije podataka

Bucket Sort Complexity Analiza

Vremenska sloลพenost sortiranja po segmentima

  • Sloลพenost u najboljem sluฤaju: Ako su svi elementi niza ravnomjerno rasporeฤ‘eni i prethodno sortirani unutar svake ฤ‡elije, potrebno je O(n) vremena za rasprลกivanje elemenata u odgovarajuฤ‡e ฤ‡elije. Zatim se svaka ฤ‡elija sortira pomoฤ‡u umetanje sortirati koลกta O(k). Stoga je ukupna sloลพenost O(n+k).
  • Prosjeฤna sloลพenost sluฤaja: Za prosjeฤne sluฤajeve pretpostavljamo da su ulazi jednoliko rasporeฤ‘eni. Stoga algoritam Bucket Sort postiลพe linearnu vremensku sloลพenost od O(n+k). Ovdje je potrebno O(n) vremena za rasprลกivanje elemenata i O(k) vremena za njihovo sortiranje pomoฤ‡u sortiranja umetanjem.
  • Sloลพenost u najgorem sluฤaju: U najgorem sluฤaju, elementi nisu jednoliko rasporeฤ‘eni i koncentriraju se u jednoj ili dvije kante. U tom sluฤaju, Bucket Sort se ponaลกa sliฤno kao algoritam sortiranja mjehuriฤ‡imaDakle, u najgorem sluฤaju, vremenska sloลพenost Bucket sortiranja je O(nยฒ).

Prostorna sloลพenost bucket sortiranja

Prostorna sloลพenost sortiranja po skupinama (Bucket Sort) je O(n*k). Ovdje je n broj elemenata, a k broj skupina potrebnih za njihov smjeลกtaj tijekom sortiranja.

Pitanja i odgovori

Koristite Bucket sort kada su ulazne vrijednosti ravnomjerno rasporeฤ‘ene u poznatom rasponu, posebno za brojeve s pomiฤnim zarezom u [0.0, 1.0]. Pruลพa linearno vrijeme na takvim podacima, ali slabo funkcionira na klasteriranim ili nepoznatim distribucijama.

Sortiranje pomoฤ‡u kanti je stabilno kada je unutarnji algoritam sortiranja koji se koristi unutar svake kante stabilan. Sortiranje umetanjem ฤuva relativni redoslijed jednakih elemenata, pa se standardna implementacija sortiranja pomoฤ‡u kanti smatra stabilnom.

Bucket Sort grupira elemente prema rasponu vrijednosti i sortira svaku ฤ‡eliju drugim algoritmom. Radix Sort grupira brojeve znamenku po znamenku i interno koristi sortiranje brojanjem. Bucket Sort preferira jednoliko rasporeฤ‘ene float brojeve; Radix Sort preferira cijele brojeve ili nizove fiksne ลกirine.

Vremenska sloลพenost sortiranja po skupinama u najgorem sluฤaju je O(nยฒ). To se dogaฤ‘a kada svi ulazni elementi padnu u jednu skupinu, prisiljavajuฤ‡i unutarnje sortiranje (obiฤno sortiranje umetanjem) da se ponaลกa kvadratno. Uniformna distribucija izbjegava ovaj scenarij.

Da. Za obradu negativnih vrijednosti, pronaฤ‘ite i minimum i maksimum, a zatim izraฤunajte indeks spremnika koristeฤ‡i (element โ€“ โ€‹โ€‹minimum) / raspon. To pomiฤe negativne vrijednosti u nenegativni indeksni prostor i omoguฤ‡uje standardnoj logici sortiranja spremnika da nastavi nepromijenjena.

Platforme pokretane umjetnom inteligencijom kao ลกto su VisuAlgo, Algorithm Visualizer i ChatGPT-generirani korak-po-korak tracPomaลพu uฤenicima da vizualiziraju Bucket Sort. Animiraju faze rasprลกivanja, sortiranja i sakupljanja, ลกto olakลกava razumijevanje matematike indeksiranja i logike particioniranja.

Preporuฤitelji voฤ‘eni umjetnom inteligencijom analiziraju veliฤinu skupa podataka, distribuciju vrijednosti i ograniฤenja memorije kako bi predloลพili odgovarajuฤ‡i algoritam. Za jednoliko rasporeฤ‘ene float brojeve, takvi sustavi preferiraju Bucket Sort. Za mijeลกane cjelobrojne raspone, mogu predloลพiti quicksort ili Radix Sort.

Saลพmite ovu objavu uz: