1. 程式人生 > >演算法導論之桶排序

演算法導論之桶排序

桶排序(bucket sort)假設輸入資料服從均勻分佈。平均情況下他的時間代價是O(n)。
計數排序假設輸入資料分佈於一個小區間的整數,而桶排序則假設輸入是一個隨機過程產生的,該過程將元素均勻獨立地分佈於[0,1)區間上。 1.桶排序的基本思想 桶排序將[0,1)區間劃分為n個相同的大小的子區間,這些子區間被稱為桶。然後將n個輸入元素分別放入各自的桶中。因為輸入時均勻獨立的,所以一般不會有很多數同時落在一個桶中的情況。這樣,我們想對各個桶中的資料進行排序,然後遍歷每個桶,按照次序把各個桶中的元素列出來即可。 一個桶排序的示例如圖: 


簡單來說就是把陣列 arr 劃分為n個大小相同子區間(桶),每個子區間各自排序,最後合併。
這樣說是不是和分治法有點像了 啊!因為分治法就是分解 —— 解決 ——合併
這樣的套路。我認為這樣想沒毛病。可以理解為桶排序是一種特殊的分治法,特殊的地方主要體現在前兩部分(這樣說不知道對不對~)。 具體來說如下: 分解部分,採用了計數排序類似的思想,通過分解,雖然沒有比較,但是將資料基本按照大小劃分了幾個區間。 針對輸入資料均勻分佈的特點,因此將資料分佈的區間可以均勻分為n個子區間。 import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; /** * 桶排序(bucket sort)假設輸入資料服從均勻分佈。平均情況下他的時間代價是O(n)。 * 計數排序假設輸入資料分佈於一個小區間的整數,而桶排序則假設輸入是一個隨機過程產生的,該過程將元素均勻獨立地分佈於[0,1)區間上。 * 1.桶排序的基本思想 * 桶排序將[0,1)區間劃分為n個相同的大小的子區間,這些子區間被稱為桶。然後將n個輸入元素分別放入各自的桶中。 * 因為輸入時均勻獨立的,所以一般不會有很多數同時落在一個桶中的情況。這樣,我們想對各個桶中的資料進行排序, * 然後遍歷每個桶,按照次序把各個桶中的元素列出來即可。 * 簡單來說就是把陣列arr劃分為n個大小相同子區間(桶),每個子區間各自排序,最後合併。 * 這樣說是不是和分治法有點像了啊!因為分治法就是分解(分桶) —— 解決(排序) ——合併這樣的套路 */ public class BucketSort { // public static void bucketSort(int[] A) { // //1. 構造桶 // //1.1 確定桶的個數n // int n = A.length; // //1.2 宣告並初始化一個List,存放連結串列; // List<ArrayList<Integer>> Blist = new ArrayList<>(n); // for(int i = 0; i < n; i++) // Blist.add(new ArrayList<Integer>()); // //2.將陣列中的元素放到桶中 // //2.1 確定元素的最值 // int max = Integer.MIN_VALUE; // int min = Integer.MAX_VALUE; // for(int a : A){ // max = Math.max(max, a); // min = Math.min(min, a); // } // //2.2 確定每個元素放入桶的編號並放進去 // for(int i : A){ // //2.2.1 確定桶的編號 // int len = A.length; // //加1是為了保證inde< A.length,防止程式丟擲IndexOutofBoundsEx; // int index = (int)((i-min) / (max-min+1.0) * A.length); // //2.2.2 放入對應的桶中 // Blist.get(index).add(i); // } // //3.桶內排序 // for(int i = 0; i < Blist.size(); i++){ // java.util.Collections.sort(Blist.get(i)); // } // //4.合併資料 // int j = 0; // for(ArrayList<Integer> arr : Blist){ // for(int i : arr){ // A[j++] = i; // } // } // } //第二種分桶的方法 public static void bucketSort(int[] arr){ int max = Integer.MIN_VALUE; int min = Integer.MAX_VALUE; for(int i = 0; i < arr.length; i++){ max = Math.max(max, arr[i]); min = Math.min(min, arr[i]); } //桶數 int bucketNum = (max - min) / arr.length + 1; ArrayList<ArrayList<Integer>> bucketArr = new ArrayList<>(); for(int i = 0; i < bucketNum; i++){ bucketArr.add(new ArrayList<Integer>()); } //將每個元素放入桶 for(int i = 0; i < arr.length; i++){ int num = (arr[i] - min) / (arr.length); bucketArr.get(num).add(arr[i]); } //對每個桶進行排序 for(int i = 0; i < bucketArr.size(); i++){ Collections.sort(bucketArr.get(i)); } //合併資料 int j = 0; for(ArrayList<Integer> arrTemp : bucketArr){ for(int i : arrTemp){ arr[j++] = i; } } } public static void main(String[] args) { int A[]={2,5,3,30,2,3,0,6,7,2,1,4,3,20}; BucketSort.bucketSort(A); System.out.println(Arrays.toString(A)); } }