我們在平時的開發中,排序演算法可以說是最常用的演算法之一,不同的排序演算法,有著不一樣的效能消耗,雖說前端開發對演算法的要求沒有那麼高,但是對於一些常見的演算法,我們還是要掌握的,它屬於乙個開發者的基本功,今天,我們就來總結一下常見的排序演算法,請看下面這張表:
下面排序都以由小到大排序為目的
1、基本思想:兩個數比較大小,較大的往下沉,較小的冒上來
2、過程
分析上面的過程,就好像乙個冒泡的過程,較小的資料不斷往上冒,較大的資料不斷往下沉,這也是氣泡排序名稱的由來
3、**實現
// 兩個數比較大小,較大的往下沉,較小的冒上來
public void bubblesort(int array) }}
}}
4、平均時間複雜度:o(n2)5、優化氣泡排序會一次將當前最小的資料排在第1、2...n-2、n-1個位置上,上面的**中,在排某個位置的資料時,即使從這個位置到最後乙個位置資料已經排序好了,還是會繼續進行迴圈直到第n-1個位置。這就造成了不必要的浪費,我們知道,在上面的排序過程中,只要前面的資料大於後面的資料,就會進行資料交換,如果某次排序沒有進行資料交換,則說明後面的資料都已經排序好了,不需要繼續迴圈處理排序了。基於上面的思想,我們可以加上乙個標誌位,記錄每次排序過程中是否進行了資料交換,如果有資料交換則繼續,如果沒有資料交換則證明資料已經排序完畢,退出迴圈,**如下:
// 兩個數比較大小,較大的往下沉,較小的冒上來
public void bubblesort(int array)
}if (!flag) }}
}
上面的**較少了一些多餘的資料比較。
1、基本思想:假設前k個資料已經排序好,迴圈遍歷第k-n個元素, 找到最小元素的位置,比較最小元素的位置是否是第k個位置,如果不是則將第k個元素和最小元素交換資料,這樣第k個位置的元素就排序好了,反覆迴圈直到第n-1個位置排上了正確的資料
2、過程
3、**實現
// 每次找到最小元素位置,和第乙個資料交換
public void selectsort(int array) else }}
}}
4、平均時間複雜度:o(n2)
1、基本思想:將資料分為若干組,分別對每組資料進行插入排序,排序完後縮小分組組數繼續重複上面過程直到只有一組資料,然後對這一組資料進行插入排序即可完成整個排序過程。希爾排序是為了縮小插入排序資料交換的次數,在普通的插入排序中,每次將元素插入到對應的位置都需要進行較多次數的移動,但是如果資料序列基本有序,插入排序的資料移動次數會大大減小,希爾排序就是基於以上思想,將資料分為若干組,分別對每一組資料進行插入排序,使得資料越來越有序,當分組為1時,資料已經基本有序,在使用插入排序效率就會大大提高。
2、過程
3、**實現
// 希爾排序,將資料分為若干組,分別對每組資料進行插入排序,排序完後縮小分組組數繼續重複上面過程直到只有一組資料,然後對這一組資料進行插入排序即可完成整個排序過程
public void shellsort(int array) }}
}grap = grap / 2; // 每次處理完縮小grap的值}}
}
4、時間複雜度:o(n2)1、基本思想:快速排序是一種效率很高的排序演算法,其主要思想是在所有元素中任意取乙個元素key,將比其小的元素統一放在其左邊,將比其大的元素放在其右邊,這樣,我們就將所有元素分為了兩個部分,比key小的在key的左邊,比key大的在key的右邊,然後我們繼續基於以上思想分別對key左邊的元素和右邊的元素進行排序,排序完畢後,所有元素也就排序完成了。快速排序的核心思想是分治,採用分而治之的方法,將乙個複雜的問題簡單化,可以大大提高效率。
2、過程
3、**實現
// 快速排序,採用分治的思想,在所有元素中任意取乙個值key,將比其大的元素排在key的左邊,比其小的元素排在陣列的右邊,然後分別對左右兩邊的元素進行快速排序
public void quicksort(int array, int start, int end)
if (start < end)
if (j != i)
while (i4、時間複雜度:o(n*logn)
1、基本思想:歸併排序的基本思想是將資料分為兩個部分,然後分別對其進行排序,最後將兩個有序陣列進行合併,合併完成後整個陣列也就排序完成了。歸併排序的核心思想也是分治,將複雜的問題簡單化,最後我們只需要關注資料合併的邏輯。
2、過程
3、**實現
// 歸併排序
public void memerysort(int array, int start, int end, int temp) }}
// 合併排序好的兩個分組(start到middle是乙個分組,middle+1到end時乙個分組)
private void memery(int array, int start, int middle, int end, int temp) else
}while (i <= middle)
while (j <= end)
for (int ii = start; ii <= end; ii++)
}
在實現歸併排序函式時,首先要了解它的核心思想:將兩個有序陣列合併。所以我們先要寫合併的函式,我們在這裡用start、middle、end來將陣列分為兩個部分,並且合併需要乙個臨時陣列,這個臨時陣列最好是由外部傳入,使得整個歸併排序共用乙個臨時陣列,這樣可以減少頻繁建立陣列的消耗。寫好合併演算法後,我們再來寫歸併排序的演算法,因為是遞迴呼叫,所以歸併排序需要傳入start、end來標記需要排序的部分,並且需要傳入乙個臨時陣列提供給合併函式。首先我們要判斷排序的部分是否大於乙個元素,如果只有乙個元素則不用進行排序,然後將需要排序部分從中間分開,分別對兩部分進行歸併排序(遞迴呼叫歸併排序函式),排序好了,然後呼叫合併函式對兩部分資料進行合併即可。
4、時間複雜度:o(n*logn)
1、基本思想:將整數按位數切割成不同的數字,然後按每個位數分別比較。
2、過程
基數排序將對整個陣列的排序轉換為對陣列資料單個位數的排序,因為單個位數上只有可能出現0-9這10個數字,我們可以通過記錄每一位數字出現的次數來完成排序過程,具體排序過程見**
3、**實現
// 基數排序,依次根據每一位的值排序陣列,最終完成排序
public void radixsort(int array)
}// 根據對應位數的值排列陣列,如果exp為1表示根據個位數的值來排列,如果exp=10表示根據十位數來排列,以此類推
private void countsort(int array, int exp)
// 複製臨時陣列到array中
for (int i=0; i基爾排序是一種很巧妙的排序演算法,它將對整個資料的排序問題轉換為對資料的每一位進行排序,因為每一位可能的取值是固定的,可以通過陣列記錄每個可能取值出現的次數,在通過計算就能知道每個可能取值所在的區間範圍,然後依次將其對應的資料插入到區間即可完成單個位數的排序。
1、基本思想:將待排序序列構造成乙個大頂堆,此時,整個序列的最大值就是堆頂的根節點。將其與末尾元素進行交換,此時末尾就為最大值。然後將剩餘n-1個元素重新構造成乙個堆,這樣會得到n個元素的次小值。如此反覆執行,便能得到乙個有序序列了。
對排序設計到很多資料結構二叉樹方面的知識,具體演算法等以後有時間再分析,可以參考:**排序演算法(三)之堆排序,這篇文章講的很詳細。
排序演算法是我們平時開發中最常見也是最基礎的演算法,這篇文章借少了八大排序演算法並提供了其**實現,每種演算法的消耗和適用場景都不一樣。在這八大排序演算法中,冒泡、選擇、插入是最原始的排序演算法,效能一般,希爾排序算是對插入排序的一種改進演算法,它縮小了資料的交換次數。快速排序、歸併排序、基數排序、堆排序這四種排序演算法的效能會好一些,其中,快速排序和歸併排序是重點,快速排序和歸併排序的核心思想都是分治,不斷的縮小排序陣列的大小來提高效能。基數排序也是一種很好的排序演算法,它將對整個陣列的排序問題轉換為依次對每一位位數上的資料進行排序,而每一位位數的可能取值是有限的(0-9),我們可以通過記錄每一位數字出現的次數來完成排序過程。堆排序充分利用了完全二叉樹的特性。我們在學習演算法時,主要是學習演算法的思想,盡量能夠達到舉一反三的效果,比如歸併排序和快速排序中用到的分治的思想,就是很多演算法的核心思想之一。
常見排序演算法總結
sort.cpp 定義控制台應用程式的入口點。include stdafx.h include using namespace std const int len 100 class csort 注意此處應該有分號 csort csort length len 建構函式,初始化陣列 arr j 1 ...
常見排序演算法總結
1.氣泡排序 蠻力法 基本思想 兩兩比較相鄰記錄,如果反序側交換,直到沒有反序的記錄為止。如果是正序排,將待排序的元素看作是豎著排列的 氣泡 較小的元素比較輕,從而要往上浮。時間複雜度 o n n void bubblesort int a,int n 優化的氣泡排序 if flag 0 break...
常見排序演算法(總結)
演算法名 時間複雜度 空間複雜度 穩定性氣泡排序o n2 o 1 不穩定 選擇排序o n2 o 1 不穩定 插入排序o n2 o 1 穩定 歸併排序o nlog n o n 可以優化到o 1 穩定 快速排序o nlog n o logn n 不穩定 堆排序o n logn o 1 不穩定 希爾排序o...