桶排序,是一種基於非比較的排序方式,時間複雜度o(n),因此它是是屬於一種「線性排序」。
思想:桶排序的思想是將一組資料分到幾個有序的桶裡,每個桶裡的資料再單獨進行快速排序。每個桶內都排序完成後,再加上本身桶之間已經是有序的,那麼按照桶的順序依次取出每個桶內的資料,最終組成的序列就是有序的。
假如排序陣列的元素個數為n,均勻分布在個數為m的桶中,那麼每個桶中的元素個數為k=n/m,因為每個桶快速排序的時間複雜度為klogk即n/mlog(n/m),那麼m個桶一起就是nlog(n/m),假如桶的個數m跟元素個數n十分接近,那麼最終的時間複雜度為o(n).
如果極端情況下,所有的元素n個都分在乙個桶裡呢?這種情況下時間複雜度就退化成o(nlogn)了。
所以,可以看出桶排序對資料及其分布的要求是十分苛刻的:
1 要求各個桶之間是有序的,這樣每個桶排好序之後,才可以直接根據桶的順序得到最終排序。
2 每個桶之間資料分布式平均的,如果出現上述極端情況,則時間複雜度就會退化為o(nlogn)了。
package com.study.algorithm.sort;
/** * @description:桶排序演算法
*/public class bucketsort
// 陣列最小值
int minvalue = arr[0];
// 陣列最大值
int maxvalue = arr[1];
for (int i = 0; i < arr.length; i++) else if (arr[i] > maxvalue)
}// 桶數量
int bucketcount = (maxvalue - minvalue) / bucketsize + 1;
int buckets = new int[bucketcount][bucketsize];
int indexarr = new int[bucketcount];
// 將陣列中值分配到各個桶裡
for (int i = 0; i < arr.length; i++)
buckets[bucketindex][indexarr[bucketindex]++] = arr[i];
}// 對每個桶進行排序,這裡使用了快速排序
int k = 0;
for (int i = 0; i < buckets.length; i++)
quicksortc(buckets[i], 0, indexarr[i] - 1);
for (int j = 0; j < indexarr[i]; j++) }}
/*** 陣列擴容
** @param buckets
* @param bucketindex
*/private static void ensurecapacity(int buckets, int bucketindex)
buckets[bucketindex] = newarr;
}/**
* 快速排序遞迴函式
** @param arr
* @param p
* @param r
*/private static void quicksortc(int arr, int p, int r)
int q = partition(arr, p, r);
quicksortc(arr, p, q - 1);
quicksortc(arr, q + 1, r);
}/**
* 分割槽函式
** @param arr
* @param p
* @param r
* @return 分割槽點位置
*/private static int partition(int arr, int p, int r)
}swap(arr, i, r);
return i;
}/**
* 交換
** @param arr
* @param i
* @param j
*/private static void swap(int arr, int i, int j)
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}}
桶排序適合用在外部排序中,就是資料儲存在外部磁碟上,由於伺服器記憶體有限無法一次性載入到記憶體中。
比如現在有10g訂單資料存在外部磁碟的乙個檔案中,我們想將這10g的訂單資料按照從小到大進行排序,但是由於伺服器記憶體有限只有幾百m,無法一次性載入記憶體,這時候就可以利用桶排序進行解決了。
思路:可以先找出這批訂單的最大值和最小值,比如掃瞄一遍檔案,最大值是10萬,最小值是1元,那麼我們可以將這10g的訂單分別劃分到100個桶中,比如:1元到1000元的放在第乙個桶內,1001到2000元的放到第二個桶內,以此類推。每個桶我們最終都會生成乙個檔案,這個小檔案中存放的都是之前劃分的那些訂單資料,我們進行乙個編號,比如(00,01,02,...99).
理想情況:
理想情況下,這10萬的訂單資料均勻分布到100個桶中,每個桶都存放1000個訂單,每個桶即每個子檔案大約是儲存100m的資料,那麼這100個子檔案依次載入到記憶體中進行快速排序,排序完成後。我們依次讀取每個子檔案的資料並寫入到乙個大檔案中,這樣以來這10g的資料就排序完成了。
實際情況:
實際情況是這10g訂單資料不可能是均勻分布的,一般人買東西肯定是金額低的多一些,金額高的就很少了,所以每個桶內不可能是很均勻的,這種情況的處理辦法就是繼續劃分這個資料量大的桶為幾個子桶,一直到每個桶的資料可以被一次性讀入記憶體為止。
由於桶排序是如果基於快排實現,就不是穩定的排序演算法。
如果是基於歸併排序實現的,則可以完成穩定的排序。
桶排序每個桶需要用到外部儲存空間,所以不是原地排序演算法。
排序演算法 氣泡排序的時間複雜度分析
氣泡排序演算法是一種基於比較的排序演算法,每次冒泡過程,都會有乙個資料確定位置。經過n次冒泡後,就有n個資料確定了位置。如圖所示,對陣列 4,5,6,3,2,1 進行氣泡排序。氣泡排序演算法 param arr param n public static void bubblesort int ar...
排序演算法 選擇排序的時間複雜度分析
選擇排序思想跟插入排序很像,也將陣列分為未排序區間和已排序區間。不同的是,選擇排序是將未排序區間中選擇乙個最小值放在已排序區間的後邊。跟插入排序不同,不需要不停往後移動資料,選擇排序直接替換最小值到指定位置即可。也很簡單 選擇排序 param a param n public static void...
幾種排序演算法的時間複雜度分析
1.選擇排序 不穩定,時間複雜度 o n 2 選擇排序的基本思想是對待排序的記錄序列進行n 1遍的處理,第i遍處理是將l i.n 中最小者與l i 交換位置。這樣,經過i遍處理之後,前i個記錄的位置已經是正確的了。2.插入排序 穩定,時間複雜度 o n 2 插入排序的基本思想是,經過i 1遍處理後,...