Bucket sort is an efficient sorting algorithm that uses buckets to sort a collection of items. It is one of the most efficient sorting algorithms, with an average time complexity of O(n) and a worst-case time complexity of O(n^2). Bucket sort is often used in data structures and algorithms with Python due to its efficient performance and ease of implementation.

In this article, we will cover the basics of bucket sort, including how the algorithm works, its time and space complexity, and a Python code example to illustrate the algorithm. We will also provide some coding exercises at the end of the article to test the reader’s understanding of bucket sort.

What is Bucket Sort?

Bucket sort is an efficient sorting algorithm that works by dividing a collection of items into buckets, then sorting each bucket independently. It is a comparison-based sorting algorithm, meaning it uses comparisons between elements to determine the order of the elements.

Bucket sort is often used to sort a collection of items with a small range of values, such as integers between 0 and 10. The algorithm works by first creating a number of buckets, then distributing the items into the buckets based on the item’s value. Once the items are distributed into the buckets, the buckets are sorted using a sorting algorithm of choice (typically insertion sort or selection sort). Finally, the sorted buckets are combined into a single sorted collection.

How Does Bucket Sort Work?

Bucket sort works by first dividing a collection of items into buckets, then sorting each bucket independently. The algorithm works as follows:

  • Create a number of buckets.
  • Distribute the items into the buckets based on the item’s value.
  • Sort each bucket using a sorting algorithm of choice (typically insertion sort or selection sort).
  • Combine the sorted buckets into a single sorted collection.

Let’s look at an example to illustrate how bucket sort works. Suppose we have the following collection of integers:

[7, 3, 5, 2, 1, 9, 4, 8, 6]

We can divide the collection into 8 buckets, with each bucket containing a range of values. For example, the first bucket could contain all integers from 0 to 1, the second from 2 to 3, and so on. The buckets would look like this:

Bucket 1 [0, 1]

Bucket 2 [2, 3]

Bucket 3 [4, 5]

Bucket 4 [6, 7]

Bucket 5 [8, 9]

Once the buckets are created, we can distribute the items into the buckets based on their value. For example, the number 7 would go into the fourth bucket, 3 into the second bucket, and so on. The buckets would now look like this:

Bucket 1 [1]

Bucket 2 [2, 3]

Bucket 3 [4, 5]

Bucket 4 [6, 7]

Bucket 5 [8, 9]

Next, we can sort each bucket using a sorting algorithm of choice. For this example, we will use insertion sort to sort each bucket. After sorting, the buckets would look like this:

Bucket 1 [1]

Bucket 2 [2, 3]

Bucket 3 [4, 5]

Bucket 4 [6, 7]

Bucket 5 [8, 9]

Finally, we can combine the sorted buckets into a single sorted collection. The resulting collection would look like this:

[1, 2, 3, 4, 5, 6, 7, 8, 9]

Time Complexity of Bucket Sort

The time complexity of bucket sort is dependent on the sorting algorithm used to sort each bucket. In general, the best-case time complexity of bucket sort is O(n), while the worst-case time complexity is O(n^2).

The best-case time complexity of bucket sort occurs when the buckets are already sorted, meaning the sorting algorithm used to sort each bucket has a time complexity of O(1). In this scenario, the time complexity of bucket sort is O(n), since it only takes one pass through the buckets to combine them into a single sorted collection.

The worst-case time complexity of bucket sort occurs when the buckets are not sorted, meaning the sorting algorithm used to sort each bucket has a time complexity of O(n^2). In this scenario, the time complexity of bucket sort is O(n^2), since it takes n passes through the buckets to combine them into a single sorted collection.

Space Complexity of Bucket Sort

The space complexity of bucket sort is O(n). This is because, in the worst case, the algorithm requires additional space to store the buckets and the sorted items.

Python Code Example

Now that we have covered the basics of bucket sort, let’s look at a Python code example to illustrate the algorithm. The following code implements bucket sort using the insertion sort algorithm to sort each bucket.

# Function to sort an array using bucket sort 
def bucket_sort(arr): 
	# Get the maximum and minimum values in the array 
	max_val = max(arr) 
	min_val = min(arr) 

	# Create buckets for each value 
	buckets = [[] for _ in range(min_val, max_val + 1)] 

	# Distribute the array values into the buckets 
	for i in range(len(arr)): 
		buckets[arr[i] - min_val].append(arr[i]) 

	# Sort each bucket using insertion sort 
	for i in range(len(buckets)): 
		insertion_sort(buckets[i]) 

	# Combine the sorted buckets 
	sorted_arr = [] 
	for i in range(len(buckets)): 
		sorted_arr.extend(buckets[i]) 

	return sorted_arr 

# Function to sort a bucket using insertion sort 
def insertion_sort(arr): 
	for i in range(1, len(arr)): 
		key = arr[i] 
		j = i-1
		while j >= 0 and key < arr[j] : 
				arr[j + 1] = arr[j] 
				j -= 1
		arr[j + 1] = key 

# Driver code 
arr = [7, 3, 5, 2, 1, 9, 4, 8, 6] 
sorted_arr = bucket_sort(arr) 

# Print the sorted array 
print(sorted_arr) 

# Output: [1, 2, 3, 4, 5, 6, 7, 8, 9]

Conclusion

In this article, we have covered the basics of bucket sort, including how the algorithm works, its time and space complexity, and a Python code example to illustrate the algorithm. Bucket sort is an efficient sorting algorithm with an average time complexity of O(n) and a worst-case time complexity of O(n^2). It is often used to sort a collection of items with a small range of values, such as integers between 0 and 10.

Exercises

Write a Python function that implements bucket sort using selection sort to sort each bucket.

# Function to sort an array using bucket sort 
def bucket_sort(arr): 
	# Get the maximum and minimum values in the array 
	max_val = max(arr) 
	min_val = min(arr) 

	# Create buckets for each value 
	buckets = [[] for _ in range(min_val, max_val + 1)] 

	# Distribute the array values into the buckets 
	for i in range(len(arr)): 
		buckets[arr[i] - min_val].append(arr[i]) 

	# Sort each bucket using selection sort 
	for i in range(len(buckets)): 
		selection_sort(buckets[i]) 

	# Combine the sorted buckets 
	sorted_arr = [] 
	for i in range(len(buckets)): 
		sorted_arr.extend(buckets[i]) 

	return sorted_arr 

# Function to sort a bucket using selection sort 
def selection_sort(arr): 
	for i in range(len(arr)): 
		# Find the minimum element in the unsorted array 
		min_idx = i 
		for j in range(i+1, len(arr)): 
			if arr[min_idx] > arr[j]: 
				min_idx = j 

		# Swap the found minimum element with the first element 
		arr[i], arr[min_idx] = arr[min_idx], arr[i] 

Write a Python function that implements bucket sort using quick sort to sort each bucket.

# Function to sort an array using bucket sort 
def bucket_sort(arr): 
	# Get the maximum and minimum values in the array 
	max_val = max(arr) 
	min_val = min(arr) 

	# Create buckets for each value 
	buckets = [[] for _ in range(min_val, max_val + 1)] 

	# Distribute the array values into the buckets 
	for i in range(len(arr)): 
		buckets[arr[i] - min_val].append(arr[i]) 

	# Sort each bucket using quick sort 
	for i in range(len(buckets)): 
		quick_sort(buckets[i], 0, len(buckets[i])-1) 

	# Combine the sorted buckets 
	sorted_arr = [] 
	for i in range(len(buckets)): 
		sorted_arr.extend(buckets[i]) 

	return sorted_arr 

# Function to sort a bucket using quick sort 
def quick_sort(arr, low, high): 
	if low < high: 
		# Partition the array 
		pi = partition(arr, low, high) 

		# Sort the elements before and after the partition 
		quick_sort(arr, low, pi-1) 
		quick_sort(arr, pi+1, high) 

# Function to partition the array 
def partition(arr, low, high): 
	i = (low-1)		 # Index of smaller element 
	pivot = arr[high]	 # Pivot 

	for j in range(low, high): 

		# If current element is smaller than or 
		# equal to pivot 
		if arr[j] <= pivot: 
		
			# Increment index of smaller element 
			i = i+1
			arr[i],arr[j] = arr[j],arr[i] 

	arr[i+1],arr[high] = arr[high],arr[i+1] 
	return (i+1)  

Write a Python program to generate a collection of random integers between 0 and 10 and sort them using bucket sort.

# Function to sort an array using bucket sort 
def bucket_sort(arr): 
	# Get the maximum and minimum values in the array 
	max_val = max(arr) 
	min_val = min(arr) 

	# Create buckets for each value 
	buckets = [[] for _ in range(min_val, max_val + 1)] 

	# Distribute the array values into the buckets 
	for i in range(len(arr)): 
		buckets[arr[i] - min_val].append(arr[i]) 

	# Sort each bucket using insertion sort 
	for i in range(len(buckets)): 
		insertion_sort(buckets[i]) 

	# Combine the sorted buckets 
	sorted_arr = [] 
	for i in range(len(buckets)): 
		sorted_arr.extend(buckets[i]) 

	return sorted_arr 

# Function to sort a bucket using insertion sort 
def insertion_sort(arr): 
	for i in range(1, len(arr)): 
		key = arr[i] 
		j = i-1
		while j >= 0 and key < arr[j] : 
				arr[j + 1] = arr[j] 
				j -= 1
		arr[j + 1] = key 

# Function to generate a collection of random integers 
def generate_random_ints(n): 
	arr = [] 
	for _ in range(n): 
		arr.append(random.randint(0, 10)) 
	return arr 

# Driver code 
arr = generate_random_ints(10) 
sorted_arr = bucket_sort(arr) 

# Print the sorted array 
print(sorted_arr) 

Write a Python program to generate a collection of random items and sort them using bucket sort.

import random 

# Function to sort an array using bucket sort 
def bucket_sort(arr): 
	# Get the maximum and minimum values in the array 
	max_val = max(arr) 
	min_val = min(arr) 

	# Create buckets for each value 
	buckets = [[] for _ in range(min_val, max_val + 1)] 

	# Distribute the array values into the buckets 
	for i in range(len(arr)): 
		buckets[arr[i] - min_val].append(arr[i]) 

	# Sort each bucket using insertion sort 
	for i in range(len(buckets)): 
		insertion_sort(buckets[i]) 

	# Combine the sorted buckets 
	sorted_arr = [] 
	for i in range(len(buckets)): 
		sorted_arr.extend(buckets[i]) 

	return sorted_arr 

# Function to sort a bucket using insertion sort 
def insertion_sort(arr): 
	for i in range(1, len(arr)): 
		key = arr[i] 
		j = i-1
		while j >= 0 and key < arr[j] : 
				arr[j + 1] = arr[j] 
				j -= 1
		arr[j + 1] = key 

# Function to generate a collection of random items 
def generate_random_items(n): 
	arr = [] 
	for _ in range(n): 
		arr.append(random.randint(0, 10)) 
	return arr 

# Driver code 
arr = generate_random_items(10) 
sorted_arr = bucket_sort(arr) 

# Print the sorted array 
print(sorted_arr) 

What is the space complexity (worst) of Bucket Sort?

O(n)