Java排序算法總結

1. 總體介紹

分類

  排序大的分類能夠分爲兩種,內排序和外排序。在排序過程當中,所有記錄存放在內存,則稱爲內排序,若是排序過程當中須要使用外存,則稱爲外排序。主要須要理解的都是內排序算法:算法

  內排序能夠分爲如下幾類:shell

  (1)、插入排序:直接插入排序、二分法插入排序、希爾排序。性能

  (2)、選擇排序:簡單選擇排序、堆排序。ui

  (3)、交換排序:冒泡排序、快速排序。spa

  (4)、歸併排序指針

  (5)、基數排序blog

性能對比

穩定性:就是能保證排序前兩個相等的數據其在序列中的前後位置順序與排序後它們兩個前後位置順序相同。即若是A i == A j,A i 原來在 A j 位置前,排序後 A i  仍然是在 A j 位置前。排序

  不穩定:簡單選擇排序、快速排序、希爾排序、堆排序不是穩定的排序算法遞歸

  穩定:冒泡排序、直接插入排序、二分法插入排序,歸併排序和基數排序都是穩定的排序算法。內存

時間複雜度:一個算法執行所耗費的時間。

  O(nlogn):快速排序,歸併排序,希爾排序,堆排序。

  O(n^2):直接插入排序,簡單選擇排序,冒泡排序。

  O(n): 桶、箱、基數排序

  快速排序是目前基於比較的內部排序中最好的方法, 其次是歸併和希爾,堆排序在數據量很大時效果明顯。當數據是隨機分佈時快速排序的平均時間最短。

空間複雜度:運行完一個程序所需內存的大小。

解釋:n: 數據規模;k:「桶」的個數;In-place: 佔用常數內存,不佔用額外內存;Out-place: 佔用額外內存。

 

排序方法的選擇

  1.數據規模很小(插入、簡單選擇、冒泡)

    (1)數據基本有序的狀況下,可選直接插入排序

    (2)數據無序時,對穩定性不做要求宜用簡單選擇排序,對穩定性有要求宜用插入或冒泡

  2.數據規模通常(快速排序、歸併排序)

  (1)徹底能夠用內存空間,序列雜亂無序,對穩定性沒有要求,快速排序,此時要付出log(N)的額外空間。

  (2)序列自己可能有序,對穩定性有要求,空間容許下,宜用歸併排序

  3.數據規模很大(歸併、桶)

     (1)對穩定性有求,則可考慮歸併排序。

      (2)對穩定性沒要求,宜用堆排序

  4.待排序列初始基本有序(正序),宜用直接插入,冒泡

 

 2. 插入排序(Insertion Sort)

  基本思想:依次遍歷元素,在已排序的序列中找到合適的位置將當前遍歷的元素插入,直到全部元素都已排序。

  方法:直接插入排序、二分插入排序、希爾排序

2.1 直接插入排序

算法思想:

  • <1>.從第一個元素開始,該元素能夠認爲已經被排序;
  • <2>.取出下一個元素,在已經排序的元素序列中從後向前掃描;
  • <3>.若是該元素(已排序)大於新元素,將該已排序元素移到下一位置;
  • <4>.重複步驟3,直到找到已排序的元素小於或者等於新元素的位置;
  • <5>.將新元素插入到該位置後;
  • <6>.重複步驟2~5。

時間複雜度:平均狀況下:O(n­2)
        最好的狀況下:正序有序(從小到大),這樣只須要比較n次,不須要移動。所以時間複雜度爲O(n)  
        最壞的狀況下:逆序有序,這樣每個元素就須要比較n次,共有n個元素,所以實際複雜度爲O(n­2)  
穩定性:穩定。由算法思想易知,反向遍歷已排序元素,若已排序元素小於等於當前元素,則將當前元素插入該已排序元素後的位置,所以相對順序不變,插入排序是穩定的。     

 

2.2 二分排序(折半插入排序)

二分法查找基本思想:對於一個有序的待查序列,定義三個指針low、high、mid,分別指向待查序列所在範圍的下界、上界及區間中間位置,即mid=(low+high)/2。對比待查數據與mid所指的值,若相等則查找成功並返回mid,若待查數小於mid值,則令high=mid-1,不然令low=mid+1,獲得新的須要查找的區間,如此循環直到找出或找不到。以下示例:

二分排序:從第二個數開始日後遍歷,用二分法查找合適的插入位置。當low<high條件不成立時說明找到合適位置,將low及以後元素後移

時間複雜度:二分插入排序的比較次數與待排序記錄的初始狀態無關,僅依賴於記錄的個數。當n較大時,比直接插入排序的最大比較次數少得多。但大於直接插入排序的最小比較次數。算法的移動次數與直接插入排序算法的相同,最壞的狀況爲n2/2,最好的狀況爲n,平均移動次數爲O(n2)。  

穩定性:穩定。

2.3 希爾排序(Shell Sort)

基本思想:希爾排序也是一種插入排序方法,其實是一種分組插入方法。先取定一個小於n的整數d1做爲第一個增量,這樣能夠把表的所有記錄分紅d1個組:全部距離爲d1的倍數的記錄放在同一個組中,在各組內進行直接插入排序;而後,取第二個增量d2(<d1),重複上述的分組和排序,直至所取的增量dt=1(dt<dt-1<…<d2<d1),即全部記錄放在同一組中進行直接插入排序爲止。

  希爾排序的核心在於間隔序列的設定。既能夠提早設定好間隔序列,也能夠動態的定義間隔序列。

時間複雜度:  平均狀況下:O(N*logN)
       最好狀況:因爲希爾排序的好壞和步長d的選擇(di到di+1的選擇策略)有不少關係,所以,目前尚未得出最好的步長如何選擇(如今有些比較好的選擇了,但不肯定是不是最好的)。因此,不知道最好的狀況下的算法時間複雜度。  
       最壞狀況:O(N*logN),最壞的狀況下和平均狀況下差很少。  

穩定性:因爲屢次插入排序,咱們知道一次插入排序是穩定的,不會改變相同元素的相對順序,但在不一樣趟的插入排序過程當中,相同的元素可能在各自的插入排序中移動,最後其穩定性就會被打亂,因此shell排序是不穩定的。(有個猜想,方便記憶:通常來講,若存在不相鄰元素間交換,則極可能是不穩定的排序。)

 

 

 

解釋:就是將增量(d)爲1的直接插入排序,增量改成從d到1的遞減。再也不是相鄰元素間的對比,而是以d爲間隔的對比插入。

3. 交換排序

3.1 冒泡排序(Bubble Sort)

基本思想經過無序區中相鄰記錄關鍵字間的比較和位置的交換,使關鍵字最小的記錄如氣泡通常逐漸往上「漂浮」直至「水面」。

時間複雜度:平均O(n2)

  最好狀況:正序有序,則只須要比較n次。故,爲O(n)  
  最壞狀況:  逆序有序,則須要比較(n-1)+(n-2)+……+1,故,爲O(N2)

穩定性:穩定。排序過程當中只交換相鄰兩個元素的位置。所以,當兩個數相等時,是不必交換兩個數的位置的。因此相對位置並無改變,冒泡排序算法是穩定的! 

算法描述:

  • <1>.比較相鄰的元素。若是第一個比第二個大,就交換它們兩個;
  • <2>.對每一對相鄰元素做一樣的工做,從開始第一對到結尾的最後一對,這樣在最後的元素應該會是最大的數;
  • <3>.針對全部的元素重複以上的步驟,除了最後一個;
  • <4>.重複步驟1~3,直到排序完成

3.2 快速排序(Quick Sort)

基本思想:由冒泡排序改進而來的。在待排序的n個記錄中任取一個記錄(一般取第一個記錄),把該記錄放入適當位置後,數據序列被此記錄劃分紅兩部分。全部關鍵字比該記錄關鍵字小的記錄放置在前一部分,全部比它大的記錄放置在後一部分,並把該記錄排在這兩部分的中間(稱爲該記錄歸位)。

核心思想:經過一趟排序將待排記錄分隔成獨立的兩部分,其中一部分記錄的關鍵字均比另外一部分的關鍵字小,則可分別對這兩部分記錄繼續進行排序,以達到整個序列有序。

時間複雜度:O(N*logN)

  最好的狀況:由於每次都將序列分爲兩個部分(通常二分都複雜度都和logN相關),故爲 O(N*logN)  
  最壞的狀況:基本有序時,退化爲冒泡排序,幾乎要比較N*N次,故爲O(N*N)

穩定性:不穩定。因爲每次都須要和中軸元素(不必定相鄰)交換,所以原來的順序就可能被打亂。快速排序是不穩定的。

算法描述:

快速排序使用分治法來把一個串(list)分爲兩個子串(sub-lists)。具體算法描述以下:

  • <1>.從數列中挑出一個元素,稱爲 "基準"(pivot);
  • <2>.從新排序數列,全部元素比基準值小的擺放在基準前面,全部元素比基準值大的擺在基準的後面(相同的數能夠到任一邊)。在這個分區退出以後,該基準就處於數列的中間位置。這個稱爲分區(partition)操做;
  • <3>.遞歸地(recursive)把小於基準值元素的子數列和大於基準值元素的子數列排序。
相關文章
相關標籤/搜索