JAVA十大排序算法之桶排序詳解
桶排序
桶排序是計(jì)數(shù)排序的升級(jí),計(jì)數(shù)排序可以看成每個(gè)桶只存儲(chǔ)相同元素,而桶排序每個(gè)桶存儲(chǔ)一定范圍的元素,通過函數(shù)的某種映射關(guān)系,將待排序數(shù)組中的元素映射到各個(gè)對應(yīng)的桶中,對每個(gè)桶中的元素進(jìn)行排序(有可能再使用別的排序算法或是以遞歸方式繼續(xù)使用桶排序),最后將非空桶中的元素逐個(gè)放入原序列中。
桶排序需要盡量保證元素分散均勻,否則當(dāng)所有數(shù)據(jù)集中在同一個(gè)桶中時(shí),桶排序失效。

代碼實(shí)現(xiàn)
1.找出數(shù)組中的最大值max和最小值min,可以確定出數(shù)組所在范圍min~max
2.根據(jù)數(shù)據(jù)范圍確定桶的數(shù)量
1.若桶的數(shù)量太少,則桶排序失效
2.若桶的數(shù)量太多,則有的桶可能,沒有數(shù)據(jù)造成空間浪費(fèi)
所以桶的數(shù)量由我們自己來確定,但盡量讓元素平均分布到每一個(gè)桶里,這里提供一個(gè)方式
(最大值 - 最小值)/每個(gè)桶所能放置多少個(gè)不同數(shù)值+1
3.確定桶的區(qū)間,一般是按照(最大值 - 最小值)/桶的數(shù)量來劃分的,且左閉右開
public class BucketSort {
public static final int[] ARRAY = {35, 23, 48, 9, 16, 24, 5, 11, 32, 17};
/**
* @param bucketSize 作為每個(gè)桶所能放置多少個(gè)不同數(shù)值,即數(shù)值的類型
* 例如當(dāng)BucketSize==5時(shí),該桶可以存放{1,2,3,4,5}這幾種數(shù)字,
* 但是容量不限,即可以存放100個(gè)3
*/
public static List<Integer> sort(List<Integer> array, int bucketSize) {
if (array == null || array.size() < 2)
return array;
int max = array.get(0), min = array.get(0);
// 找到最大值最小值
for (int i = 0; i < array.size(); i++) {
if (array.get(i) > max)
max = array.get(i);
if (array.get(i) < min)
min = array.get(i);
}
//獲取桶的數(shù)量
int bucketCount = (max - min) / bucketSize + 1;
//構(gòu)建桶,初始化
List<ArrayList<Integer>> bucketArr = new ArrayList<>(bucketCount);
List<Integer> resultArr = new ArrayList<>();
for (int i = 0; i < bucketCount; i++) {
bucketArr.add(new ArrayList<>());
}
//將原數(shù)組的數(shù)據(jù)分配到桶中
for (int i = 0; i < array.size(); i++) {
//區(qū)間范圍
bucketArr.get((array.get(i) - min) / bucketSize).add(array.get(i));
}
for (int i = 0; i < bucketCount; i++) {
if (bucketSize == 1) {
for (int j = 0; j < bucketArr.get(i).size(); j++)
resultArr.add(bucketArr.get(i).get(j));
} else {
if (bucketCount == 1)
bucketSize--;
//對桶中的數(shù)據(jù)再次用桶進(jìn)行排序
List<Integer> temp = sort(bucketArr.get(i), bucketSize);
for (int j = 0; j < temp.size(); j++)
resultArr.add(temp.get(j));
}
}
return resultArr;
}
public static void print(List<Integer> array) {
for (int i : array) {
System.out.print(i + " ");
}
System.out.println("");
}
public static void main(String[] args) {
print(Arrays.stream(ARRAY).boxed().collect(Collectors.toList()));
System.out.println("============================================");
print(sort(Arrays.stream(ARRAY).boxed().collect(Collectors.toList()), 2));
}
}
時(shí)間復(fù)雜度
桶排序算法遍歷了2次原始數(shù)組,運(yùn)算量為2N,最后,遍歷桶輸出排序結(jié)果的運(yùn)算量為N,初始化桶的運(yùn)算量為M。
對桶進(jìn)行排序,不同的排序算法算法復(fù)雜度不同,冒泡排序算法復(fù)雜度為O(N^2),堆排序、歸并排序算法復(fù)雜度為O(NlogN),我們以排序算法復(fù)雜度為O(NlogN)進(jìn)行計(jì)算,運(yùn)算量為N/M * log(N/M) * M
最終的運(yùn)算量為3N+M+N/M * log(N/M) * M,即3N+M+N(logN-logM),去掉系數(shù),時(shí)間復(fù)雜度為O(N+M+N(logN-logM))
算法穩(wěn)定性
桶排序算法在對每個(gè)桶進(jìn)行排序時(shí),若選擇穩(wěn)定的排序算法,則排序后,相同元素的位置不會(huì)發(fā)生改變,所以桶排序算法是一種穩(wěn)定的排序算法。
總結(jié)
本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Go Java算法之K個(gè)重復(fù)字符最長子串詳解
這篇文章主要為大家介紹了Go Java算法之K個(gè)重復(fù)字符最長子串詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08
SpringBoot中實(shí)現(xiàn)訂單30分鐘自動(dòng)取消的項(xiàng)目實(shí)踐
現(xiàn)在電子商務(wù)平臺(tái)上訂單創(chuàng)建成功,等待支付,一般會(huì)給30分鐘的時(shí)間,本文主要介紹了SpringBoot中實(shí)現(xiàn)訂單30分鐘自動(dòng)取消的項(xiàng)目實(shí)踐,具有一定的參考價(jià)值,感興趣的可以了解一下2023-10-10
java中javamail發(fā)送帶附件的郵件實(shí)現(xiàn)方法
這篇文章主要介紹了java中javamail發(fā)送帶附件的郵件實(shí)現(xiàn)方法,較為詳細(xì)的分析了JavaMail發(fā)送郵件的用法,是非常實(shí)用的技巧,需要的朋友可以參考下2015-01-01
教你springboot+dubbo快速啟動(dòng)的方法
這篇文章主要介紹了springboot+dubbo快速啟動(dòng)的方法,dubbo的角色廣泛的分為三類provider,comsumer,注冊中心,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下2022-04-04
mybaties plus實(shí)體類設(shè)置typeHandler不生效的解決
這篇文章主要介紹了mybaties plus實(shí)體類設(shè)置typeHandler不生效的解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08
Spring @Bean注解的使用場景與案例實(shí)現(xiàn)
隨著SpringBoot的流行,我們現(xiàn)在更多采用基于注解式的配置從而替換掉了基于XML的配置,所以本篇文章我們主要探討基于注解的@Bean以及和其他注解的使用2023-03-03

