桶排序是指:將待排序數組中的元素划分為多個桶(范圍段),對每個桶分別進行排序,將多個桶組合即為排序結果。
桶排序的時間復雜度為O(n + c), 其中n為待排序數據量,c = n * (logn - logm), m為桶的個數。極端情況下,當桶的個數與數據量相等時,桶排序時間復雜度為O(n)。
看一些博客里寫道桶排序是穩定排序,另一些博客則說是非穩定排序。實際上,桶排序的穩定性取決於桶內排序所使用的算法,若使用插入排序,則是穩定排序,若使用快排,則是非穩定排序。
1 import java.util.Arrays; 2 3 public class BucketSort { 4 public static void main(String[] args) { 5 int[] array = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; 6 bucketSort(array); 7 System.out.println(Arrays.toString(array)); 8 } 9 10 public static void bucketSort(int[] arr) { 11 if (arr == null || arr.length == 0) { 12 return; 13 } 14 int len = arr.length; 15 // 根據原始序列的長度,設置桶的數量。這里假設每個桶放最多放4個元素 16 int bucketCount = len / 4; 17 // 遍歷原始序列,找出最大值和最小值 18 int min = 0, max = 0; 19 for (int i = 0; i < len; i++) { 20 if (arr[i] > max) { 21 max = arr[i]; 22 } else if (arr[i] < min) { 23 min = arr[i]; 24 } 25 } 26 // 每個桶的數值范圍 27 int range = (max - min + 1) / bucketCount; 28 int[][] buckets = new int[bucketCount][]; 29 // 遍歷原始序列 30 for (int i = 0; i < len; i++) { 31 int val = arr[i]; 32 // 計算當前值屬於哪個桶 33 int bucketIndex = (int) Math.floor((val - min) / range); 34 // 向桶中添加元素 35 buckets[bucketIndex] = appendItem(buckets[bucketIndex], val); 36 } 37 // 最后合並所有的桶 38 int k = 0; 39 for (int[] b : buckets) { 40 if (b != null) { 41 for (int i = 0; i < b.length; i++) { 42 arr[k++] = b[i]; 43 } 44 } 45 } 46 } 47 48 private static int[] appendItem(int[] bucketArr, int val) { 49 if (bucketArr == null || bucketArr.length == 0) { 50 return new int[]{val}; 51 } 52 // 拷貝一下原來桶的序列,並增加一位 53 int[] arr = Arrays.copyOf(bucketArr, bucketArr.length + 1); 54 // 這里使用插入排序,將新的值val插入到序列中 55 int i; 56 for (i = arr.length - 2; i >= 0 && arr[i] > val; i--) { 57 // 從新序列arr的倒數第二位開始向前遍歷(倒數第一位是新增加的空位,還沒有值) 58 // 如果當前序列值大於val,那么向后移位 59 arr[i + 1] = arr[i]; 60 } 61 arr[i + 1] = val; 62 return arr; 63 } 64 }