Algoritmus řazení segmentů (Java, Python, C/C++ Code Příklady)
Co je bucket Sort?
Bucket sort, často nazývaný bin sort, je metoda srovnávacího třídění, která přijímá nesetříděné pole jako vstup a jako výsledek vytváří setříděné pole. Tato metoda funguje tak, že se prvky rozdělí do několika segmentů a každý z těchto segmentů se seřadí jednotlivě podle libovolného třídícího algoritmu, jako je vkládání. Poté se všechny segmenty sloučí a vytvoří setříděné pole.
Třídění segmentů se běžně používá, když jsou prvky-
- Hodnoty s pohyblivou řádovou čárkou
- Rovnoměrně distribuováno v rozsahu
Časová složitost třídění segmentů závisí na počtu použitých segmentů a rovnoměrnosti rozložení vstupů. Zatímco různé třídící algoritmy jako např shell sort, sloučit řazení, hromadné řazení a rychlé řazení může dosáhnout časové složitosti v nejlepším případě O(n*logn), algoritmus pro třídění segmentů může dosáhnout stejného v lineární časové složitosti nebo O(n).
Řazení segmentů se řídí metodou rozptylu a sběru. Při použití tohoto přístupu jsou prvky rozmístěny do odpovídajících segmentů, roztříděny v segmentech a jako poslední krok shromážděny do seřazeného pole. Tento přístup s rozptylem je diskutován v následující části
Scatter-Gather-Approach
Rozsáhlé a složité problémy mohou být občas náročné na řešení. Rozptylový přístup se pokouší vyřešit takové problémy rozdělením celé datové sady do shluků. Poté je každý shluk adresován samostatně a vše se znovu spojí, aby se získala konečná odpověď.
Takto algoritmus třídění segmentu implementuje metodu rozptylu:
Jak funguje třídění kbelíků
Základní pracovní princip třídění lopatek je následující:
- Vytvoří se sada prázdných kbelíků. Na základě různých zásad se počet segmentů může lišit.
- Ze vstupního pole vložte každý prvek do příslušného segmentu.
- Roztřiďte ty kbelíky jednotlivě.
- Spojte setříděné segmenty a vytvořte jediné výstupní pole.
Podrobné pracovní kroky jsou uvedeny v následujících částech.
Nepravý 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: Algoritmus třídění segmentů pro plovoucí desetinnou čárku Numbers
Algoritmus třídění segmentu pro čísla s plovoucí desetinnou čárkou v rozsahu od 0.0 do 1.0:
Krok 1) Vytvořte deset (10) prázdných segmentů tak, že první segment bude obsahovat čísla v rozsahu [0.0, 0.1). Druhý segment pak bude obsahovat [0.1, 0.2) a tak dále.
Krok 2) Pro každý prvek pole:
-
A. Vypočítejte index segmentu pomocí vzorce:
index segmentu= no_of_buckets *prvek_pole
-
b. Vložte prvek do bucketu[bucket_index]
Krok 3) Seřaďte každý segment jednotlivě pomocí řazení vložení.
Krok 4) Spojte všechny segmenty do jednoho pole.
Podívejme se na příklad třídění kbelíku. V tomto příkladu seřadíme následující pole pomocí algoritmu třídění bucket-
Krok 1) Nejprve si vytvoříme 10 prázdných kbelíků. První segment bude obsahovat čísla mezi [0.0, 0.1). Potom bude druhý segment obsahovat čísla mezi [0.1, 0.2) a tak dále.
Krok 2) Pro každý prvek pole vypočítáme index bucketu a umístíme prvek do tohoto bucketu.
Index segmentu lze vypočítat pomocí vzorce:
bucket_index= no_of_buckets*array_element
Výpočet indexu segmentu:
a) 0.78
bucket_index = no_of_buckets*array_element
= 10 * 0.78
= 7.8
Proto bude prvek 0.78 uložen na kbelíku[podlaha(7.8)] nebo kbelíku[7].
b) 0.17
bucket_index = no_of_buckets * prvek pole
= 10 * 0.17
= 1.7
Prvek pole 0.17 bude uložen na bucket[floor(1.7)] nebo bucket[1].
c) 0.39
bucket_index = no_of_buckets * prvek pole
= 10 * 0.39
= 3.9
0.39 bude uloženo na bucket[floor(3.9)] nebo bucket[3].
Po iteraci přes všechny prvky pole budou segmenty následující:
Krok 3) Poté bude každý segment setříděn pomocí řazení vložení. Po operaci třídění by výstup byl:
Krok 4) V posledním kroku budou segmenty zřetězeny do jednoho pole. Toto pole bude seřazeným výsledkem vstupu.
Každý segment bude zřetězen k výstupnímu poli. Například zřetězení prvků druhého kbelíku:
Zřetězení posledních prvků segmentu bude následující:
Po zřetězení bude výsledné pole požadované tříděné pole.
Program třídění kbelíků v C/C++
Vstup:
//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;
}
Výstup:
Sorted Output: 0.12 0.17 0.21 0.23 0.26 0.39 0.69 0.72 0.78 0.94
Program třídění kbelíků v Python
Vstup:
# 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))
Výstup:
Sorted Output: [0.12, 0.17, 0.21, 0.23, 0.26, 0.39, 0.69, 0.72, 0.78, 0.94]
Kbelík Seřadit Java
Vstup:
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]+" ");
}
}
}
Výstup:
Sorted Output: 0.12 0.17 0.21 0.23 0.26 0.39 0.69 0.72 0.78 0.94
Metoda 2: Algoritmus třídění segmentu pro celočíselné prvky
Algoritmus třídění segmentu pro vstup, který obsahuje čísla mimo rozsah [0.0, 1.0], se trochu liší od předchozího algoritmus. Kroky potřebné pro tento případ jsou následující -
Krok 1) Najděte maximální a minimální prvky.
Krok 2) Vyberte počet segmentů n a inicializujte tyto segmenty jako prázdné.
Krok 3) Vypočítejte rozsah nebo rozsah každého segmentu pomocí vzorce:
span = (maximum - minimum)/n
Krok 4) Pro každý prvek pole:
-
1. Vypočítejte index segmentu:
bucket_index = (element - minimum)/span-
2. Vložte prvek do bucket[bucket_index]
Krok 5) Seřaďte každý segment pomocí řazení vložení.
Krok 6) Spojte všechny segmenty do jednoho pole.
Podívejme se na příklad tohoto algoritmu řazení segmentů. V tomto příkladu seřadíme následující pole pomocí algoritmu třídění bucket-
Krok 1) V prvním kroku je potřeba najít maximum a minimum prvků daného pole. Pro tento příklad je maximum 24 a minimum 1.
Krok 2) Nyní musíme vybrat počet prázdných kbelíků, n. V tomto příkladu vezmeme 5 kbelíků. Poté je inicializujeme jako prázdné.
Krok 3) Rozpětí každého segmentu je třeba vypočítat podle následujícího vzorce:
span = (maximum-minimum)/n = (24-1)/5 = 4;
První segment tedy bude obsahovat čísla v rozsahu [0, 5). Druhý segment bude obsahovat čísla v [5, 10) a tak dále.
Krok 4) Pro každý prvek pole vypočítáme index bucketu a umístíme prvek do tohoto bucketu. Index segmentu lze vypočítat pomocí vzorce:
bucket_index = (element - minimum)/span
Výpočet indexu segmentu:
-
a) 11bucket_index = (prvek – minimum)/rozpětí
=(11-1)/4
=2
Prvek 11 tak bude uložen v kbelíku[2].
-
b) 9
bucket_index = (prvek – minimum)/rozpětí
=(9-1)/4
=2
Poznámka: Protože 9 je hraniční prvek pro bucket[1], je třeba jej přidat do bucketu[1] namísto přidávání do stejného segmentu předchozího prvku.
Po provedení operací pro každý prvek budou kbelíky následující:
Krok 5) Nyní bude každý segment setříděn pomocí řazení vložení. Kbelíky po třídění-
Krok 6) V posledním kroku budou segmenty zřetězeny do jednoho pole. Že řada bude seřazeným výsledkem vstupu.
Program třídění kbelíků v C/C++
Vstup:
#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;
}
Výstup:
Sorted Output:1 8 9 11 12 13 17 19 21 24
Program třídění kbelíků v Python
Vstup:
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)
Výstup:
Sorted Output: [1, 8, 9, 11, 12, 13, 17, 19, 21, 24]
Kbelík Seřadit Java
Vstup:
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 + " ");
}
}
}
Výstup:
Sorted Output: 1.0 8.0 9.0 11.0 12.0 13.0 17.0 19.0 21.0 24.0
Klady a zápory
| Klady | Nevýhody |
|---|---|
| Provádějte rychlejší výpočty | Ve srovnání s jinými algoritmy zabírá více místa |
| Lze jej použít jako externí metodu třídění | Funguje špatně, když data nejsou rovnoměrně distribuována |
| Kbelíky lze zpracovávat nezávisle |
Analýza složitosti třídění segmentů
Časová složitost třídění bucket
- Nejlepší složitost případu:Pokud jsou všechny prvky pole předem rovnoměrně rozmístěny a roztříděny, vyžadovalo by to čas O(n) k rozptýlení prvků do odpovídajících segmentů. Poté roztřiďte každý kbelík pomocí řazení řazení by stálo O(k). Celková složitost by tedy byla O(n+k).
- Průměrná složitost případu:Pro průměrné případy předpokládáme, že vstupy jsou rovnoměrně rozděleny. Algoritmus bucket sorting tedy dosahuje lineární časové složitosti O(n+k). Zde je čas O(n) potřebný pro rozptýlení prvků a čas O(k) pro třídění těchto prvků pomocí vkládání.
- Složitost nejhoršího případu:V nejhorším případě nebudou prvky rovnoměrně rozmístěny a soustředěny do jednoho nebo dvou konkrétních kbelíků. V takovém případě bude třídění segmentů fungovat jako a algoritmus pro třídění bublin. V nejhorším případě by tedy časová složitost třídění segmentů byla O(n^2).
Prostorová složitost třídění lopatek
Prostorová složitost třídění segmentu je O(n*k). Zde n je počet prvků a k je počet požadovaných segmentů.


















