Chào ace, bài này chúng ta sẽ tìm hiểu về một trong các thuật toán sắp xếp được sử dụng nhiều trong lập trình và thực tế nhất đó là Bucket Sort, sau đây cafedev sẽ giới thiệu và chia sẻ chi tiết(khái niệm, ứng dụng của nó, code ví dụ, điểm mạnh, điểm yếu…) về Bucket Sort thông qua các phần sau.
Nội dung chính
1. Giới thiệu
Sắp xếp nhóm(Bucket sort) chủ yếu hữu ích khi đầu vào được phân phối đồng đều trên một phạm vi. Ví dụ, hãy xem xét vấn đề sau đây.
Sắp xếp một tập hợp lớn các số dấu phẩy động nằm trong khoảng từ 0,0 đến 1,0 và được phân phối đồng đều trên phạm vi. Làm thế nào để chúng tôi sắp xếp các con số một cách hiệu quả?
Một cách đơn giản là áp dụng thuật toán sắp xếp dựa trên so sánh. Giới hạn dưới cho thuật toán sắp xếp dựa trên so sánh (Sắp xếp hợp nhất, Sắp xếp theo đống, Sắp xếp nhanh, v.v.) là Ω (n Log n), tức là chúng không thể làm tốt hơn nLogn.
Chúng ta có thể sắp xếp mảng theo thời gian tuyến tính không? Sắp xếp đếm không thể được áp dụng ở đây vì chúng tôi sử dụng các khóa làm chỉ mục trong sắp xếp đếm. Các phím ở đây là số dấu phẩy động.
Ý tưởng là sử dụng phân loại theo nhóm.
Sau đây là thuật toán nhóm.
bucketSort (arr [], n)
1) Tạo n nhóm trống (Hoặc danh sách).
2) Thực hiện theo sau cho mọi phần tử mảng arr [i].
……. a) Chèn arr [i] vào bucket [n * array [i]]
3) Sắp xếp các nhóm riêng lẻ bằng cách sử dụng sắp xếp chèn.
4) Ghép tất cả các thùng đã phân loại.
2. Code ví dụ với nhiều ngôn ngữ
C/C++
// C++ program to sort an array using bucket sort
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
// Function to sort arr[] of size n using bucket sort
void bucketSort(float arr[], int n)
{
// 1) Create n empty buckets
vector<float> b[n];
// 2) Put array elements in different buckets
for (int i = 0; i < n; i++) {
int bi = n * arr[i]; // Index in bucket
b[bi].push_back(arr[i]);
}
// 3) Sort individual buckets
for (int i = 0; i < n; i++)
sort(b[i].begin(), b[i].end());
// 4) Concatenate all buckets into arr[]
int index = 0;
for (int i = 0; i < n; i++)
for (int j = 0; j < b[i].size(); j++)
arr[index++] = b[i][j];
}
/* Driver program to test above function */
int main()
{
float arr[] = { 0.897, 0.565, 0.656, 0.1234, 0.665, 0.3434 };
int n = sizeof(arr) / sizeof(arr[0]);
bucketSort(arr, n);
cout << "Sorted array is \n";
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
return 0;
}
Java
// Java program to sort an array
// using bucket sort
import java.util.*;
import java.util.Collections;
class GFG {
// Function to sort arr[] of size n
// using bucket sort
static void bucketSort(float arr[], int n)
{
if (n <= 0)
return;
// 1) Create n empty buckets
@SuppressWarnings("unchecked")
Vector<Float>[] buckets = new Vector[n];
for (int i = 0; i < n; i++) {
buckets[i] = new Vector<Float>();
}
// 2) Put array elements in different buckets
for (int i = 0; i < n; i++) {
float idx = arr[i] * n;
buckets[(int)idx].add(arr[i]);
}
// 3) Sort individual buckets
for (int i = 0; i < n; i++) {
Collections.sort(buckets[i]);
}
// 4) Concatenate all buckets into arr[]
int index = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < buckets[i].size(); j++) {
arr[index++] = buckets[i].get(j);
}
}
}
// Driver code
public static void main(String args[])
{
float arr[] = { (float)0.897, (float)0.565,
(float)0.656, (float)0.1234,
(float)0.665, (float)0.3434 };
int n = arr.length;
bucketSort(arr, n);
System.out.println("Sorted array is ");
for (float el : arr) {
System.out.print(el + " ");
}
}
}
Python
# Python3 program to sort an array
# using bucket sort
def insertionSort(b):
for i in range(1, len(b)):
up = b[i]
j = i - 1
while j >= 0 and b[j] > up:
b[j + 1] = b[j]
j -= 1
b[j + 1] = up
return b
def bucketSort(x):
arr = []
slot_num = 10 # 10 means 10 slots, each
# slot's size is 0.1
for i in range(slot_num):
arr.append([])
# Put array elements in different buckets
for j in x:
index_b = int(slot_num * j)
arr[index_b].append(j)
# Sort individual buckets
for i in range(slot_num):
arr[i] = insertionSort(arr[i])
# concatenate the result
k = 0
for i in range(slot_num):
for j in range(len(arr[i])):
x[k] = arr[i][j]
k += 1
return x
# Driver Code
x = [0.897, 0.565, 0.656,
0.1234, 0.665, 0.3434]
print("Sorted Array is")
print(bucketSort(x))
Kết quả
Sorted array is
0.1234 0.3434 0.565 0.656 0.665 0.897
3. Độ phức tạp
Độ phức tạp về thời gian: Nếu chúng ta giả sử rằng việc chèn vào một nhóm mất O (1) thời gian thì bước 1 và 2 của thuật toán trên rõ ràng sẽ mất O (n) thời gian. O (1) có thể dễ dàng nếu chúng ta sử dụng một danh sách liên kết để biểu diễn một nhóm (Trong đoạn mã sau, vectơ C ++ được sử dụng để đơn giản hóa). Bước 4 cũng mất O (n) thời gian vì sẽ có n mục trong tất cả các nhóm.
Bước chính để phân tích là bước 3. Bước này trung bình cũng mất O (n) thời gian nếu tất cả các số được phân bố đồng đều (vui lòng tham khảo sách CLRS để biết thêm chi tiết)
Nguồn và Tài liệu tiếng anh tham khảo:
Tài liệu từ cafedev:
- Full series tự học Cấu trúc dữ liệu và giải thuật từ cơ bản tới nâng cao tại đây nha.
- Ebook về Cấu trúc dữ liệu và giải thuật tại đây.
- Các series tự học lập trình khác
Nếu bạn thấy hay và hữu ích, bạn có thể tham gia các kênh sau của cafedev để nhận được nhiều hơn nữa:
Chào thân ái và quyết thắng!