乾貨總結:編程過程中常見的排序算法精講

排序(Sorting) 是計算機程序設計中的一種重要操作,功能是

將一個數據元素(或記錄)的任意序列,重新排列成一個關鍵字有序的序列。

作為程序員,方方面面都需要用到算法,其中排序算法是要經常使用到的一種,所以很有必要了解和掌握各種常見排序算法。

通常來說,排序就是把集合中的元素按照一定的次序排序在一起。一般來說有升序排列和降序排列2種排序方式,而常見的排序算法有6種:

  • 冒泡排序(Bubble Sort)
  • 選擇排序(Selection Sort)
  • 插入排序(Insertion Sort)
  • 歸併排序(Merge Sort)
  • 快速排序(Quick Sort)
  • 堆排序(Heap Sort)

Bubble Sort

冒泡排序(Bubble Sort)是一種簡單的排序算法。它重複地走訪過要排序的數列,一次比較兩個元素,如果它們的順序錯誤就把它們交換過來。

走訪數列的工作是重複地進行直到沒有再需要交換,也就是說該數列已經排序完成。這個算法的名字由來是因為越小的元素會經由交換慢慢“浮”到數列的頂端。

乾貨總結:編程過程中常見的排序算法精講

算法描述:

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

代碼實現:

乾貨總結:編程過程中常見的排序算法精講

Selection Sort

選擇排序(Selection-sort)是一種簡單直觀的排序算法。它也是表現最穩定的排序算法之一,因為無論什麼數據進去都是O(n2)的時間複雜度,所以用到它的時候,數據規模越小越好。

它的工作原理:

首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然後,再從剩餘未排序元素中繼續尋找最小(大)元素,然後放到已排序序列的末尾。以此類推,直到所有元素均排序完畢。

乾貨總結:編程過程中常見的排序算法精講

算法描述:n個記錄的直接選擇排序可經過n-1趟直接選擇排序得到有序結果。

具體如下:

  1. 初始狀態:無序區為R[1..n],有序區為空;
  2. 第i趟排序(i=1,2,3…n-1)開始時,當前有序區和無序區分別為R[1..i-1]和R(i..n)。該趟排序從當前無序區中-選出關鍵字最小的記錄 R[k],將它與無序區的第1個記錄R交換,使R[1..i]和R[i+1..n)分別變為記錄個數增加1個的新有序區和記錄個數減少1個的新無序區;
  3. n-1趟結束,數組有序化了。

代碼實現:

乾貨總結:編程過程中常見的排序算法精講

Insertion Sort

插入排序(Insertion-Sort)的算法描述是一種簡單直觀的排序算法。

工作原理是通過構建有序序列,對於未排序數據,在已排序序列中從後向前掃描,找到相應位置並插入。

插入排序在實現上,通常採用in-place排序(即只需用到O(1)的額外空間的排序),因而在從後向前掃描過程中,需要反覆把已排序元素逐步向後挪位,為最新元素提供插入空間。

乾貨總結:編程過程中常見的排序算法精講

算法描述:

  1. 一般來說,插入排序都採用in-place在數組上實現。具體算法描述如下:
  2. 從第一個元素開始,該元素可以認為已經被排序;
  3. 取出下一個元素,在已經排序的元素序列中從後向前掃描;
  4. 如果該元素(已排序)大於新元素,將該元素移到下一位置;
  5. 重複步驟3,直到找到已排序的元素小於或者等於新元素的位置;
  6. 將新元素插入到該位置後;
  7. 重複步驟2~5。

代碼實現:

乾貨總結:編程過程中常見的排序算法精講

Merge Sort

歸併排序(Merge Sort)是建立在歸併操作上的一種有效的排序算法。該算法是採用分治法(Divide and Conquer)的一個非常典型的應用。

歸併排序是一種穩定的排序方法。將已有序的子序列合併,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。若將兩個有序表合併成一個有序表,稱為2-路歸併。

乾貨總結:編程過程中常見的排序算法精講

歸併排序和選擇排序一樣,歸併排序的性能不受輸入數據的影響,但表現比選擇排序好的多,因為始終都是O(n log n)的時間複雜度,代價是需要額外的內存空間。

算法描述:

  1. 把長度為n的輸入序列分成兩個長度為n/2的子序列;
  2. 對這兩個子序列分別採用歸併排序;
  3. 將兩個排序好的子序列合併成一個最終的排序序列。

代碼實現:

乾貨總結:編程過程中常見的排序算法精講

Quick Sort

快速排序(Quick Sort)的基本思想:通過一趟排序將待排記錄分隔成獨立的兩部分,其中一部分記錄的關鍵字均比另一部分的關鍵字小,則可分別對這兩部分記錄繼續進行排序,以達到整個序列有序。

乾貨總結:編程過程中常見的排序算法精講

算法描述:

  1. 快速排序使用分治法來把一個串(list)分為兩個子串(sub-lists)。具體算法描述如下:
  2. 從數列中挑出一個元素,稱為 “基準”(pivot);
  3. 重新排序數列,所有元素比基準值小的擺放在基準前面,所有元素比基準值大的擺在基準的後面(相同的數可以到任一邊)。在這個分區退出之後,該基準就處於數列的中間位置。這個稱為分區(partition)操作;
  4. 遞歸地(recursive)把小於基準值元素的子數列和大於基準值元素的子數列排序。

代碼實現:

乾貨總結:編程過程中常見的排序算法精講

乾貨總結:編程過程中常見的排序算法精講

Heap Sort

堆排序(Heap Sort)是指利用堆這種數據結構所設計的一種排序算法。堆積是一個近似完全二叉樹的結構,並同時滿足堆積的性質:即子結點的鍵值或索引總是小於(或者大於)它的父節點。

乾貨總結:編程過程中常見的排序算法精講

算法描述:

  1. 將初始待排序關鍵字序列(R1,R2….Rn)構建成大頂堆,此堆為初始的無序區;
  2. 將堆頂元素R[1]與最後一個元素R[n]交換,此時得到新的無序區(R1,R2,……Rn-1)和新的有序區(Rn),且滿足R[1,2…n-1]<=R[n];
  3. 由於交換後新的堆頂R[1]可能違反堆的性質,因此需要對當前無序區(R1,R2,……Rn-1)調整為新堆,然後再次將R[1]與無序區最後一個元素交換,得到新的無序區(R1,R2….Rn-2)和新的有序區(Rn-1,Rn)。不斷重複此過程直到有序區的元素個數為n-1,則整個排序過程完成。

代碼實現:

乾貨總結:編程過程中常見的排序算法精講

乾貨總結:編程過程中常見的排序算法精講

算法比較

乾貨總結:編程過程中常見的排序算法精講

用上訴幾種算法對10000個整數的隨機數組進行測試,結果如下:

乾貨總結:編程過程中常見的排序算法精講

冒泡排序在性能方面最差, 堆排和快排性能最佳

更多IT乾貨文章與資訊,關注微信公眾號:DueApe(ID:DueApeTutor)獲取。


分享到:


相關文章: