排序算法總結

排序算法幾種分類方式:

1,穩(wěn)定排序和不穩(wěn)定排序

? ? ? 如果a==b, 當排序之前a在b的前面,排序后,a仍然在b的前面,則該排序算法為穩(wěn)定排序算法。否則為不穩(wěn)定排序算法。

2,非線性時間比較類排序和線性時間非比較類排序算法

? ? ? 非線性時間比較類排序:通過比較來決定元素間的相對位置,由于比較次數(shù),使其時間復雜度不能突破O(nlogn)。

? ? ? 線性時間非比較類排序:不通過比較來決定元素間的相對位置,它可以突破比較排序的時間下限,以線性時間運行。


幾種常見的排序算法介紹:

1,選擇排序

算法原理:依次在元素間比較,從集合中找出最小的元素,放到集合最前面,再從剩下的集合中找出次小的元素,再放到當前集合最前面;依次循環(huán),把所有的元素排好序。

平均時間復雜度O(n*n),空間復雜度O(1)。

選擇排序是不穩(wěn)定排序。

Java代碼?

//?選擇排序:??

public?int[]?selectSort(int[]?nums)?{??

long?start?=?System.currentTimeMillis();??

for?(int?i?=?0;?i?<?nums.length;?i++)?{??

int?minIndex?=?i;??

for?(int?j?=?i?+?1;?j?<?nums.length;?j++)?{??

if?(nums[j]?<?nums[minIndex])?{??

????????????????????minIndex?=?j;??

????????????????}??

????????????}??

????????????swap(nums,?i,?minIndex);??

????????}??

System.out.println("Select?Sort,?count?time?=?"?+?(System.currentTimeMillis()?-?start)?+?"ms");??

return?nums;??

????}??

private?void?swap(int[]?nums,?int?x,?int?y)?{??

if?(x?==?y)??

return;??

int?temp?=?nums[x];??

????????nums[x]?=?nums[y];??

????????nums[y]?=?temp;??

????}??


2,快速排序

算法原理:從元素集合中挑選出一個基準(Pivot),一次遍歷之后,把所有大于基準的元素放在基準值的右邊,所有小于基準的元素放在基準值的左邊。然后遞歸分別對左邊和右邊執(zhí)行同樣的操作。

遍歷過程如下:首先選定基準,然后分別從左邊和右邊開始遍歷,直至左右相遇則遍歷完成。左邊開始往右邊遍歷時,遇到比基準值大的元素,則停下來,右邊開始往左邊遍歷時,遇到比基準值小的元素,則停下來,然后把左右兩個元素交換。然后繼續(xù)遍歷,直至相遇。

注意:如果選定的基準是左邊第一個元素,則先從右邊開始往左遍歷,這樣能保證停下來時的元素是不大于基準的元素。反之,則從左邊開始遍歷。

平均時間復雜度O(nlogn),空間復雜度O(logn)。

快速排序是不穩(wěn)定排序

Java代碼?

//?快速排序:??

public?int[]?quickSort(int[]?nums)?{??

long?start?=?System.currentTimeMillis();??

if?(nums?==?null?||?nums.length?==?0)??

return?nums;??

quickSortByPivot(nums,0,?nums.length?-?1);??

System.out.println("Quick?Sort,?count?time?=?"?+?(System.currentTimeMillis()?-?start)?+?"ms");??

return?nums;??

????}??

private?void?quickSortByPivot(int[]?nums,?int?left,?int?right)?{??

int?l?=?left,?r?=?right;??

int?pivot?=?nums[left];??

while?(l?<?r)?{??

while?(r?>?l?&&?nums[r]?>=?pivot)??

????????????????r--;??

while?(r?>?l?&&?nums[l]?<=?pivot)??

????????????????l++;??

if?(l?<?r)??

????????????????swap(nums,?l,?r);??

????????}??

????????swap(nums,?left,?l);??


if?(l?-?1?>?left)??

quickSortByPivot(nums,?left,?l?-1);??

if?(right?>?l?+?1)??

quickSortByPivot(nums,?l?+1,?right);??

????}??



3,簡單插入排序

算法原理:把當前元素插入到已排好序的元素集合的對應位置。把第一個元素當成已經(jīng)排好序的元素,從第二個元素(新元素)開始,從排好序的元素(待比較元素)中后向前逐一掃描比較,如果待比較的元素比新元素大,則把新元素與待比較元素交換,然后新元素繼續(xù)往前比較,直至結束。當每個元素都與排好序的元素完成比較,則排序完成。

平均時間復雜度O(n*n),空間復雜度O(1)。

簡單插入排序是穩(wěn)定排序

Java代碼?

//?簡單插入排序:??

public?int[]?simpleInsertSort(int[]?nums)?{??

long?start?=?System.currentTimeMillis();??

for?(int?i?=?1;?i?<?nums.length;?i++)?{??

int?pre?=?i?-?1,?cur?=?i;??

while?(pre?>=?0?&&?nums[pre]?>?nums[cur])?{??

????????????????swap(nums,?pre,?cur);??

????????????????cur?=?pre;??

????????????????pre--;??

????????????}??

????????}??

System.out.println("Simple?Insert?Sort,count?time?=?"?+?(System.currentTimeMillis()?-?start)?+?"ms");??

return?nums;??

????}??



4,希爾(shell)排序(縮小增量排序)

算法原理:是插入排序的改進版,考慮到插入排序時,有可能某個元素需要插入到比較遠的位置,導致不斷的重復插入。因此希爾排序會優(yōu)先比較距離較遠的元素。希爾排序引入步長概念,先選定一個步長(可根據(jù)集合大小確定),然后使用插入排序思想比較相隔步長距離的各個元素。然后把步長減一,繼續(xù)比較,直至步長為1,此時相當于插入排序,但是目前的集合已經(jīng)近似有序了。

平均時間復雜度O(n^1.3),空間復雜度O(1)。

希爾排序是不穩(wěn)定排序。

Java代碼?

//?希爾排序?,??

public?int[]?shellSort(int[]?nums)?{??

long?start?=?System.currentTimeMillis();??

if?(nums?==?null?||?nums.length?==?0)??

return?null;??

int?gap?=?nums.length?/?3;//?步長??


while?(gap?>?0)?{??

for?(int?k?=?0;?k?<?gap;?k++)?{??

int?cur?=?k;??

int?pre?=?k;??

while?(cur?<?nums.length)?{??

if?(nums[cur]?<?nums[pre])?{??

????????????????????????swap(nums,?cur,?pre);??

????????????????????}??

????????????????????pre?=?cur;??

????????????????????cur?+=?gap;??

????????????????}??

????????????}??

????????????gap--;??

????????}??

System.out.println("Shell?Sort,count?time?=?"?+?(System.currentTimeMillis()?-?start)?+?"ms");??

return?nums;??

????}??



5,冒泡排序

算法原理:每次遍歷一次集合,比較相鄰元素,把較大的元素移到后面,完成一次遍歷時,則最大的元素已經(jīng)移到最后,然后繼續(xù)遍歷剩下的無序集合,把當前集合最大的移到最后面。經(jīng)歷n次遍歷后,完成排序。

冒泡排序還可以稍微改進,當排序過程中,發(fā)現(xiàn)待排序集合已經(jīng)是有序的,則可以不需要進一步遍歷了。

平均時間復雜度O(n*n),空間復雜度O(1)。

冒泡排序是穩(wěn)定排序。

Java代碼?

//?冒泡排序:??

public?int[]?bubbleSort(int[]?nums)?{??

long?start?=?System.currentTimeMillis();??

if?(nums?==?null?||?nums.length?==?0)??

return?null;??

for?(int?i?=?0;?i?<?nums.length;?i++)?{??

boolean?isSorted?=?true;//?假設當前已經(jīng)有序,冒泡排序改進,如果當前循環(huán)發(fā)現(xiàn)已經(jīng)有序,則不需要繼續(xù)遍歷。??

for?(int?j?=?1;?j?<?nums.length?-?i;?j++)?{??

if?(nums[j]?<?nums[j?-?1])?{??

swap(nums,?j,?j?-1);//?一次遍歷后,如果有交換動作,則不是有序的.??

isSorted?=false;??

????????????????}??

????????????}??

System.out.println("bubble?Sort?current?index:"?+?i);??

if?(isSorted)??

return?nums;??

????????}??

System.out.println("Bubble?Sort,count?time?=?"?+?(System.currentTimeMillis()?-?start)?+?"ms");??

return?nums;??

????}??



6,堆排序

算法原理:堆排序是利用堆這種數(shù)據(jù)結構來設計的排序算法。堆可以看做一個近似完全二叉樹的結構。堆分為大頂堆和小頂堆。大頂堆滿足如下性質,父節(jié)點的值總是大于(等于)子節(jié)點的值,小頂堆滿足如下性質,父節(jié)點的值總是小于(等于)子節(jié)點的值。

從0開始對堆中的節(jié)點進行編號,則其節(jié)點和其父節(jié)點以及子節(jié)點的編號關系如下,當前節(jié)點編號為i:

父節(jié)點編號 parent(i) = i / 2;

左子節(jié)點編號 left(i) = 2 * i + 1;

右子節(jié)點編號 right(i) = 2 * i + 2;

堆排序過程為首先根據(jù)集合元素大小建立一個大頂堆,當前的堆是無序的,然后對每個元素進行調整,使其符合大頂堆的規(guī)則,當前節(jié)點值大于等于子節(jié)點值。完成一次堆的調整后,堆的第一個元素,即堆頂元素,則為集合中的最大元素。此時堆頂元素為有序元素,把它與集合中的最后一個位置的元素互換,然后繼續(xù)為剩下的其他元素創(chuàng)建大頂堆。直至最后,所有的元素都為有序元素。

平均時間復雜度O(nlogn),空間復雜度O(1)。

堆排序是不穩(wěn)定排序。

Java代碼?

//?最大堆排序:??

public?int[]?heapSort(int[]?nums)?{??

long?start?=?System.currentTimeMillis();??

if?(nums?==?null?||?nums.length?==?0)??

return?null;??


????????buildMaxHeap(nums);??


System.out.println("Heap?Sort,count?time?=?"?+?(System.currentTimeMillis()?-?start)?+?"ms");??

return?nums;??

????}??


private?void?adjustHeapOfIndex(int[]?nums,?int?index,?int?heapSize)?{??

//?System.out.println("index|heapSize:"?+?index?+?"|"?+?heapSize);??

int?left?=?index?*?2?+?1;??

int?right?=?index?*?2?+?2;??

int?largest?=?index;??

if?(left?<?heapSize?&&?nums[left]?>?nums[largest])??

????????????largest?=?left;??

if?(right?<?heapSize?&&?nums[right]?>?nums[largest])??

????????????largest?=?right;??

if?(index?!=?largest)?{??

????????????swap(nums,?index,?largest);??

????????????adjustHeapOfIndex(nums,?largest,?heapSize);??

????????}??

//?this.printArrays("adjust?heap",?nums);??

????}??


private?int[]?buildMaxHeap(int[]?nums)?{??


int?heapSize?=?nums.length;??


while?(heapSize?>?0)?{//?從nums.length到1,不斷構建最大堆;??


//?構建最大堆;??

for?(int?i?=?heapSize?-?1;?i?>=?0;?i--)?{?//?針對每個index,不斷調整堆;??

????????????????adjustHeapOfIndex(nums,?i,?heapSize);??

????????????}??

//?this.printArrays("build?max?heap:",nums);??

swap(nums,0,?heapSize?-?1);?//?堆構建完成后?最大的值為nums[0],完后交換放到最后??


????????????heapSize--;??

????????}??


return?nums;??

????}??



7,歸并排序

?算法原理:歸并排序主要是采用分治法,把兩個已排好序的子集合合并成一個有序的集合。子集的排序則是采用遞歸方法,如果子集只包含一個元素,則為一個有序的集合。

平均時間復雜度O(nlogn),空間復雜度O(n)。

歸并排序是穩(wěn)定排序。

Java代碼?

//?歸并排序??

public?int[]?mergeSort(int[]?nums)?{??

long?start?=?System.currentTimeMillis();??

if?(nums?==?null?||?nums.length?==?0)??

return?null;??

//?System.out.println("start?to?merge?sort:");??

int[]?temp?=?new?int[nums.length];??

mergeSort(nums,0,?nums.length?-?1,?temp);??

System.out.println("Merge?Sort,count?time?=?"?+?(System.currentTimeMillis()?-?start)?+?"ms");??

return?nums;??

????}??


public?void?mergeSort(int[]?nums,?int?start,?int?end,?int[]?temp)?{??

if?(end?-?start?>?0)?{??

int?sublength?=?(end?-?start)?/?2;??

mergeSort(nums,?start,?start?+?sublength,?temp);//?分別把兩個子串排好序?即一直劃分到只剩一個元素,則就是一個排好序的子串。??

mergeSort(nums,?start?+?sublength?+1,?end,?temp);??

//?System.out.println("Merge?Sort:"?+?start?+?"|"?+?sublength?+?"|"?+?end);??

mergeArrays(nums,?start,?start?+?sublength,?start?+?sublength?+1,?end,?temp);//?把兩個排好序的子串合并??

????????}??

????}??


private?int[]?mergeArrays(int[]?nums,?int?lstart,?int?lend,?int?rstart,?int?rend,?int[]?temp)?{??

if?((lend?-?lstart)?<?0?&&?(rend?-?rstart)?<?0)??

return?nums;??


int?tempindex?=?lstart;??

int?leftindex?=?lstart,?rightindex?=?rstart;??

//?System.out.println("tempindex|leftindex?"?+?tempindex?+?"|"?+?leftindex);??

while?(leftindex?<=?lend?&&?rightindex?<=?rend)?{??

if?(nums[leftindex]?<=?nums[rightindex])?{??

????????????????temp[tempindex++]?=?nums[leftindex++];??

}else?{??

????????????????temp[tempindex++]?=?nums[rightindex++];??

????????????}??

????????}??


while?(leftindex?<=?lend)?{??

????????????temp[tempindex++]?=?nums[leftindex++];??

????????}??

while?(rightindex?<=?rend)?{??

????????????temp[tempindex++]?=?nums[rightindex++];??

????????}??

//?System.out.println("fininsh?index?"?+?tempindex?+?"|"?+?leftindex);??

for?(int?k?=?lstart;?k?<=?rend;?k++)?{//?把經(jīng)過處理的數(shù)組里的值全部更新到原數(shù)組中??

????????????nums[k]?=?temp[k];??

????????}??

//?this.printArrays("Merge?Arrays:",?nums);??

return?nums;??

????}??



8,基數(shù)排序

算法原理:基數(shù)排序是把待排序的數(shù)字分為低位和高位,低位先排序,然后收集,再按高位排序,再收集,直至最高位,則排序完成。注意基數(shù)排序無法處理負數(shù)。

排序過程為,首先得到集合中的最大數(shù),根據(jù)最大數(shù),得到需要按位循環(huán)排序的次數(shù)。

在每次按位排序時,先初始化10個桶,分別存放余數(shù)為0-9的元素個數(shù),在一次遍歷之后,10個桶中已保存各個余數(shù)出現(xiàn)的次數(shù),然后再根據(jù)余數(shù)個數(shù)更新10個桶中的相應元素應該存放的位置,比如余數(shù)為1的元素會排在余數(shù)為0的元素的后面,因此如果余數(shù)為0的元素個數(shù)為5,則余數(shù)為1的元素至少會在第5個位置之后,由此統(tǒng)計元素應該在集合中出現(xiàn)的位置。

之后再次從大到小遍歷整個集合,根據(jù)元素的余數(shù),得到對應桶的值,即為該元素在新的集合中的下標值,存放好一個元素,就把對應桶中的值相應減一。遍歷結束,則這次按位排序結束,得到一個按低位排序的集合。

再取較高位,進行排序。直至按最高位排序結束,則此時得到的集合就是一個有序的集合。

平均時間復雜度O(2n*k),k為按位排序的次數(shù);空間復雜度O(n+k),k為桶的數(shù)量;數(shù)據(jù)量大的話,k會遠遠小于n。?

基數(shù)排序是穩(wěn)定排序。

Java代碼?

//?基數(shù)排序?基數(shù)排序不能處理負數(shù);??

public?int[]?radixSort(int[]?nums)?{??

long?start?=?System.currentTimeMillis();??

if?(nums?==?null?||?nums.length?==?0)??

return?null;??


int?max?=?nums[0];??

for?(int?cur?:?nums)?{//?先得到最大數(shù)??

if?(cur?>?max)??

????????????????max?=?cur;??

????????}??


int[]?temp?=?new?int[nums.length];??


int?exp?=?1;??

do?{??

int[]?buckets?=?new?int[10];//?針對余數(shù)的桶?統(tǒng)計余數(shù)個數(shù)??

for?(int?j?=?0;?j?<?nums.length;?j++)?{??

buckets[(nums[j]?/?exp)?%10]++;//?保存每個余數(shù)出現(xiàn)的個數(shù)??

????????????}??

//?this.printArrays("buckets?nums?of?exp:"?+?exp,?buckets);??


for?(int?l?=?1;?l?<?10;?l++)?{??

buckets[l]?+=?buckets[l?-1];//?統(tǒng)計余數(shù)對應的數(shù)按順序出現(xiàn)在整個數(shù)組中的位置?即余數(shù)越小?則其在數(shù)組中排在越前面??

????????????}??

//?this.printArrays("buckets:",?buckets);??


//?this.printArrays("before?bucket:",?nums);??

//?從數(shù)組最后往前循環(huán)?因為buckets中數(shù)據(jù)的位置從大到小遞減.??

for?(int?m?=?nums.length?-?1;?m?>=?0;?m--)?{??

//?System.out.println("m,?value:"?+?m?+?"|"?+?nums[m]?+?"|"?+??

//?buckets[(nums[m]/exp)%10]);??

//?this.printArrays("nums:",?nums);??

temp[buckets[(nums[m]?/?exp)?%10]?-?1]?=?nums[m];//?每存儲一個數(shù)據(jù)后,則把buckets中對應的數(shù)據(jù)減一;??

buckets[(nums[m]?/?exp)?%10]--;??

//?this.printArrays("buckets:",?buckets);??

????????????}??


for?(int?k?=?0;?k?<?nums.length;?k++)?{//?更新值??

????????????????nums[k]?=?temp[k];??

????????????}??


//?this.printArrays("After?bucket:"?+?exp,?temp);??

exp?*=10;??

}while?(max?/?exp?>?0);??


System.out.println("Radix?Sort,count?time?=?"?+?(System.currentTimeMillis()?-?start)?+?"ms");??

return?nums;??

????}??



9,計數(shù)排序

算法原理:計數(shù)排序不是基于比較,而是將待排序的數(shù)據(jù)轉換為鍵存儲在額外開辟的數(shù)組空間中。作為一種線性時間復雜度的排序,計數(shù)排序要求待排序的數(shù)據(jù)必須是有確定范圍的整數(shù)。

排序過程為,先得到待排序數(shù)據(jù)中的最大值和最小值,然后根據(jù)最大值和最小值開辟一個新的數(shù)組空間,然后遍歷整個數(shù)據(jù)集合,統(tǒng)計各個元素出現(xiàn)的次數(shù),并且存入與元素值對應的數(shù)組下標。

然后對數(shù)組中的計數(shù)進行統(tǒng)計,計算出每個元素應該存放的位置,最后反向遍歷數(shù)據(jù)集合,根據(jù)每個元素值,在數(shù)組中獲取元素應該存放的位置。

平均時間復雜度O(n+k),空間復雜度(n+k)。k為數(shù)據(jù)集合中最大值和最小值的范圍。如果待排序集合數(shù)據(jù)比較集中,計算排序是一個很有效的排序算法。

計算排序是穩(wěn)定排序。


Java代碼?

//?計數(shù)排序??

public?int[]?countingSort(int[]?nums)?{??

long?start?=?System.currentTimeMillis();??

if?(nums?==?null?||?nums.length?==?0)??

return?null;??

//?先得到待排序數(shù)據(jù)的范圍??

int?min?=?nums[0],?max?=?nums[0];??

for?(int?curvalue?:?nums)?{??

if?(curvalue?<?min)??

????????????????min?=?curvalue;??

if?(curvalue?>?max)??

????????????????max?=?curvalue;??

????????}??


//?根據(jù)數(shù)據(jù)范圍初始化數(shù)組?進行計數(shù)??

int[]?counts?=?new?int[max?-?min?+?1];??


//?遍歷數(shù)組?進行計數(shù)??

for?(int?k?:?nums)?{??

????????????counts[k?-?min]++;??

????????}??


//?更新數(shù)組中各元素的位置??

for?(int?k?=?1;?k?<?counts.length;?k++)?{??

counts[k]?+=?counts[k?-1];??

????????}??


this.printArrays("Counting?arr:",?counts);??


int[]?temp?=?new?int[nums.length];??

for?(int?i?=?nums.length?-?1;?i?>=?0;?i--)?{??

//?System.out.println("counts?index:"?+?(nums[i]-min)?+?",count?value:"?+??

//?counts[nums[i]-min]);??

temp[counts[nums[i]?-?min]?-1]?=?nums[i];??

????????????counts[nums[i]?-?min]--;??

????????}??


for?(int?j?=?0;?j?<?nums.length;?j++)?{//?更新值??

????????????nums[j]?=?temp[j];??

????????}??


System.out.println("Counting?Sort,count?time?=?"?+?(System.currentTimeMillis()?-?start)?+?"ms");??

return?nums;??

????}??



10,桶排序

算法原理:桶排序是計數(shù)排序的升級版,利用函數(shù)的映射關系,把數(shù)據(jù)映射到有限的桶中,然后對每個桶進行單獨排序,可使用快速排序等其他算法。最后把幾個桶的元素合并,完成排序。

桶排序的時間復雜度取決于各個桶的排序算法,其他部分的時間復雜度為O(n)。顯然,桶劃分得越多,各個桶中的數(shù)據(jù)越少,每個桶的排序時間越少,效率越高,但相應的,空間消耗也越大。

平均時間復雜度O(n+k),空間復雜度O(n+k)。


Java代碼?

//?桶排序算法??

public?int[]?bucketSort(int[]?nums)?{??

long?start?=?System.currentTimeMillis();??

if?(nums?==?null?||?nums.length?==?0)??

return?null;??

if?(nums.length?<=?1)??

return?nums;??


//this.printArrays("bucket?sort:",?nums);??

//?先得到待排序數(shù)據(jù)的范圍??

int?min?=?nums[0],?max?=?nums[0];??

for?(int?curvalue?:?nums)?{??

if?(curvalue?<?min)??

????????????????min?=?curvalue;??

if?(curvalue?>?max)??

????????????????max?=?curvalue;??

????????}??


//?根據(jù)數(shù)的范圍?確定桶的個數(shù)?以及桶的映射函數(shù)??

//?在此假設最多分十個桶?然后把數(shù)據(jù)分別放入對應桶內??

//?每個桶使用List??

int?bucketNum?=?10;??

int?step?=?0;??

if?((max?-?min)?<?10)??

bucketNum?=?max?-?min?+1;??

step?=?(max?-?min?+1)?/?bucketNum;//?根據(jù)bucketNum和step分出bucketNum個桶,范圍?[min,min+step),最后一個桶還包含剩下的余數(shù);??

//?初始化桶??

List[]?buckets?=new?ArrayList[bucketNum];??

for?(int?bk?=?0;?bk?<?buckets.length;?bk++)?{??

buckets[bk]?=new?ArrayList();??

????????}??

System.out.println("Bucketnum:"?+?bucketNum);??

//?遍歷數(shù)組?把元素分別放入桶中??

for?(int?curnum?:?nums)?{??

int?curindex?=?(curnum?-?min)?/?step;??

if?(curindex?>?buckets.length?-?1)??

curindex?=?buckets.length?-1;??

System.out.println("curnum:"?+?curnum?+?",curindex?=?"?+?curindex?+?",min?=?"?+?min?+?",step?=?"?+?step);??

????????????buckets[curindex].add(curnum);??

????????}??


//?分別對各個桶進行排序?并且把每個桶中各元素合并??

int?index?=?0;??

for?(List?list?:?buckets)?{??

int[]?temp?=?new?int[list.size()];??

for?(int?k?=?0;?k?<?list.size();?k++)?{??

????????????????temp[k]?=?(Integer)?list.get(k);??

????????????}??

int[]?tempresult?=?bucketSort(temp);??

if?(tempresult?!=?null)??

for?(int?value?:?tempresult)??

????????????????????nums[index++]?=?value;??

????????}??


System.out.println("Bucket?Sort,count?time?=?"?+?(System.currentTimeMillis()?-?start)?+?"ms");??

return?nums;??

????}??



排序算法總結:

1,如果待排序的集合規(guī)模較小,如n<50,可用簡單插入排序或者選擇排序。

2,如果待排序的集合基本有序,可用簡單插入排序或者冒泡排序。

3,如果待排序的集合規(guī)模較大,則應采用時間復雜度O(nlogn)的排序方法,如快速排序,堆排序或歸并排序。

? ? ?當待排序的元素是隨機分布的,快速排序是平均時間最短的;

? ? ?堆排序雖然時間復雜度跟快速排序一樣,但是實際上的時間消耗(建堆,調整堆)會比快速排序多,因此一般選擇快速排序。

? ? ?但是相比快速排序,堆排序的空間的優(yōu)點是占用更少,也不像快速排序,會出現(xiàn)最壞的情況。

? ? ?如果需要穩(wěn)定的排序算法,則可選歸并排序。

4,堆排序適用于在一個集合n中,快速找出前m個元素(m<n),每次建堆,調整堆,都找出一個元素,執(zhí)行m次則找出前m個元素。

5,如果待排序的數(shù)據(jù)比較集中。則可以采用計數(shù)排序。

6,實際算法使用時,可以多個算法一起使用,以達到更好的效果。如歸并排序中,桶排序中,對子串的處理都可以選擇其他效率更好的算法。


每個算法代碼可見:https://github.com/yangwu/JavaDemo

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容