排序演算法 桶排序的時間複雜度分析

2021-09-26 12:51:54 字數 2972 閱讀 5403

桶排序,是一種基於非比較的排序方式,時間複雜度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遍處理後,...