排序算法的算法思想和使用場景總結
總結是對某一階段的工作、學習或思想中的經驗或情況進行分析研究的書面材料,它能夠給人努力工作的動力,讓我們抽出時間寫寫總結吧。那么總結要注意有什么內容呢?以下是小編整理的排序算法的算法思想和使用場景總結,僅供參考,大家一起來看看吧。
排序算法的算法思想和使用場景總結1
排序算法總結
所謂排序,就是要整理文件中的記錄,使之按關鍵字遞增(或遞減)次序排列起來。當待排序記錄的關鍵字都不相同時,排序結果是惟一的,否則排序結果不惟一。
在待排序的文件中,若存在多個關鍵字相同的記錄,經過排序后這些具有相同關鍵字的記錄之間的相對次序保持不變,該排序方法是穩定的;若具有相同關鍵字的記錄之間的相對次序發生改變,則稱這種排序方法是不穩定的。
要注意的是,排序算法的穩定性是針對所有輸入實例而言的。即在所有可能的輸入實例中,只要有一個實例使得算法不滿足穩定性要求,則該排序算法就是不穩定的。
一.插入排序
插入排序的基本思想是每步將一個待排序的記錄按其排序碼值的大小,插到前面已經排好的文件中的適當位置,直到全部插入完為止。插入排序方法主要有直接插入排序和希爾排序。
①.直接插入排序(穩定)接插入排序的過程為:在插入第i個記錄時,R1,R2……Ri-1已經排好序,將第i個記錄的排序碼Ki依次和R1,R2,..,Ri-1的排序碼逐個進行比較,找到適當的位置。使用直接插入排序,對于具有n個記錄的文件,要進行n-1趟排序。
代碼如下:
void Dir_Insert(int A[],int N) //直接插入排序{ int j,t;for(int i=1;it) { A[j+1]=A[j];j--;} A[j+1]=t;} }
1 ②.希爾排序(不穩定):
希爾(Shell)排序的基本思想是:先取一個小于n的整數d1作為第一個增量把文件的全部記錄分成d1個組。所有距離為d1的倍數的記錄放在同一個組中。先在各組內進行直接插入排序;然后,取得第二個增量d2 一般取d1=n/2,di+1=di/2。如果結果為偶數,則加1,保證di為奇數。 希爾排序是不穩定的,希爾排序的執行時間依賴于增量序列,其平均時間復雜度為O(n^). 代碼如下: void Shell(int A[],int n) //Shell排序{ int i,j,k,t;(n/2)%2 == 0 ? k = n/2+1:k = n/2;//保證增量為奇數 while(k > 0) { for(j=k;j=0 && A[i]>t) { A[i+k]=A[i];i=i-k;} A[i+k]=t;} if(k == 1) break;(k/2)%2 ==0 ? k=k/2+1:k=k/2;} } 二.選擇排序 選擇排序的基本思想是每步從待排序的記錄中選出排序碼最小的記錄,順序存放在已排序的記錄序列的后面,直到全部排完。選擇排序中主要使用直接選擇排序和堆排 2序。 ①.直接選擇排序(不穩定) 直接選擇排序的過程是:首先在所有記錄中選出序碼最小的記錄,把它與第1個記錄交換,然后在其余的記錄內選出排序碼最小的記錄,與第2個記錄交換......依次類推,直到所有記錄排完為止。 無論文件初始狀態如何,在第i趟排序中選出最小關鍵字的記錄,需要做n-i次比較,因此,總的比較次數為n(n-1)/2=O(n^2)。當初始文件為正序時,移動次數為0;文件初態為反序時,每趟排序均要執行交換操作,總的移動次數取最大值3(n-1)。直接選擇排序的平均時間復雜度為O(n^2)。直接選擇排序是不穩定的。 代碼如下: void Dir_Choose(int A[],int n) //直接選擇排序{ int k,t;for(int i=0;i ②.堆排序(不穩定) 堆排序是一種樹形選擇排序,是對直接選擇排序的有效改進。n個關鍵字序列K1,K2,.……,Kn稱為堆,當且僅當該序列滿足(Ki<=K2i且Ki<=k2i+1)或(ki>=K2i且Ki>=K2i+1),(1<=i<=n/2)。根結點(堆頂)的關鍵字是堆里所有結點關鍵字中最小者,稱為小根堆;根結點的關鍵字是堆里所有結點關鍵字中最大者,稱為大根堆。 3若將此序列所存儲的向量R[1..n]看作是一棵完全二叉樹的存儲結構,則堆實質上是滿足如下性質的完全二叉樹:樹中任一非葉結點的關鍵字均不大于(或不小于)其左右孩子(若存在)結點的關鍵字。 堆排序的關鍵步驟有兩個:一是如何建立初始堆;二是當堆的根結點與堆的最后一個結點交換后,如何對少了一個結點后的結點序列做調整,使之重新成為堆。堆排序的最壞時間復雜度為O(nlog2n),堆排序的平均性能較接近于最壞性能。由于建初始堆所需的比較次數較多,所以堆排序不適宜于記錄較少的文件。堆排序是就地排序,輔助空間為O(1),它是不穩定的排序方法。 代碼略.. 三.交換排序 交換排序的基本思想是:兩兩比較待排序記錄的排序碼,并交換不滿足順序要求的那寫偶對,直到滿足條件為止。交換排序的主要方法有冒泡排序和快速排序. ①.冒泡排序(穩定的) 冒泡排序將被排序的記錄數組R[1……n]垂直排列,每個記錄R[i]看作是重量為ki的氣泡。根據輕氣泡不能在重氣泡之下的原則,從下往上掃描數組R;凡掃描到違反本原則的輕氣泡,就使其向上"漂浮"。如此反復進行,直到最后任何兩個氣泡都是輕者在上,重者在下為止。 冒泡排序的具體過程如下: 第一步,先比較k1和k2,若k1>k2,則交換k1和k2所在的`記錄,否則不交換。繼續對k2和k3重復上述過程,直到處理完kn-1和kn。這時最大的排序碼記錄轉到了最后位置,稱第1次起泡,共執行n-1次比較。 與第一步類似,從k1和k2開始比較,到kn-2和kn-1為止,共執行n-2次比較。 依次類推,共做n-1次起泡,完成整個排序過程。 若文件的初始狀態是正序的,一趟掃描即可完成排序。所需關鍵字比較次數為n-1次,記錄移動次數為0。因此,冒泡排序最好的時間復雜度為O(n)。 若初始文件是反序的,需要進行n-1趟排序。每趟排序要進行n-i次關鍵字的比較(1<=i<=n-1),且每次比較都必須移動記錄三次來達到交換記錄位置。在這種情況下,比較次數達到最大值n(n-1)/2=O(n^2),移動次數也達到最大值3n(n-1)/2=O(n^2)。因此,冒泡排序的最壞時間復雜度為O(n^2)。 雖然冒泡排序不一定要進行n-1趟,但由于它的記錄移動次數較多,故平均性能比直接插入排序要差得多。冒泡排序是就地排序,且它是穩定的。 代碼如下: 4 void QP(int A[],int n) //優化的冒泡排序 { int count=0,t,flag;for(int i=0;i ②.快速排序:(不穩定的) 快速排序采用了一種分治的策略,通常稱其為分治法,其基本思想是:將原問題分解為若干個規模更小但結構與原問題相似的子問題。遞歸地解這些子問題,然后將這些子問題的解組合為原問題的解。 快速排序的具體過程如下: 第一步,在待排序的n個記錄中任取一個記錄,以該記錄的排序碼為準,將所有記錄分成兩組,第1組各記錄的排序碼都小于等于該排序碼,第2組各記錄的排序碼都大于該排序碼,并把該記錄排在這兩組中間。 第二步,采用同樣的方法,對左邊的組和右邊的組進行排序,直到所有記錄都排到相應的位置為止。 代碼如下: void Quick_Sort(int A[],int low,int high) //low和high是數組的下標{ if(low 5 { int temp,t=A[low];int l=low,h=high;while(l 四.歸并排序 歸并排序是將兩個或兩個以上的有序子表合并成一個新的有序表。初始時,把含有n個結點的待排序序列看作由n個長度都為1的有序子表組成,將它們依次兩兩歸并得到長度為2的若干有序子表,再對它們兩兩合并。直到得到長度為n的有序表,排序結束。 歸并排序是一種穩定的排序,可用順序存儲結構,也易于在鏈表上實現,對長度為n的文件,需進行log2n趟二路歸并,每趟歸并的時間為O(n),故其時間復雜度無論是在最好情況下還是在最壞情況下均是O(nlog2n)。歸并排序需要一個輔助向量來暫存兩個有序子文件歸并的結果,故其輔助空間復雜度為O(n),顯然它不是就地排序。 代碼略... 五.基數排序 設單關鍵字的每個分量的取值范圍均是C0<=Kj<=Crd-1(0<=j<=rd),可能的取值個數rd稱為基數.基數的選擇和關鍵字的分解因關鍵字的類型而異. (1).若關鍵字是十進制整數,則按個、十等位進行分解,基數rd=10,C0=0,C9=9,d為最長整數的位數. (2).若關鍵字是小寫的英文字符串,則rd=26,C0='a',C25='z',d為最長字符串的長度. 基數排序的基本思想是:從低位到高位依次對待排序的關鍵碼進行分配和收集,經過d趟分配和收集,就可以得到一個有序序列. 按平均時間將排序分為四類: (1)平方階(O(n2))排序 一般稱為簡單排序,例如直接插入、直接選擇和冒泡排序; (2)線性對數階(O(nlgn))排序 如快速、堆和歸并排序; (3)O(n1+£)階排序 £是介于0和1之間的常數,即0<£<1,如希爾排序; (4)線性階(O(n))排序 如基數排序。 各種排序方法比較 簡單排序中直接插入最好,快速排序最快,當文件為正序時,直接插入和冒泡均最佳。 影響排序效果的因素 因為不同的排序方法適應不同的應用環境和要求,所以選擇合適的排序方法應綜合考慮下列因素: ①待排序的記錄數目n; ②記錄的大小(規模); ③關鍵字的結構及其初始狀態; ④對穩定性的要求; ⑤語言工具的條件; ⑥存儲結構; ⑦時間和輔助空間復雜度等。 不同條件下,排序方法的選擇 7 (1)若n較小(如n≤50),可采用直接插入或直接選擇排序。 當記錄規模較小時,直接插入排序較好;否則因為直接選擇移動的記錄數少于直接插人,應選直接選擇排序為宜。 (2)若文件初始狀態基本有序(指正序),則應選用直接插人、冒泡或隨機的快速排序為宜; (3)若n較大,則應采用時間復雜度為O(nlgn)的排序方法:快速排序、堆排序或歸并排序。 快速排序是目前基于比較的內部排序中被認為是最好的方法,當待排序的關鍵字是隨機分布時,快速排序的平均時間最短; 堆排序所需的輔助空間少于快速排序,并且不會出現快速排序可能出現的最壞情況。這兩種排序都是不穩定的。 若要求排序穩定,則可選用歸并排序。但從單個記錄起進行兩兩歸并的排序算法并不值得提倡,通常可以將它和直接插入排序結合在一起使用。先利用直接插入排序求得較長的有序子文件,然后再兩兩歸并之。因為直接插入排序是穩定的,所以改進后的歸并排序仍是穩定的。 一、冒泡排序 已知一組無序數據a[1]、a[2]、……a[n],需將其按升序排列。首先比較a[1]與a[2]的值,若a[1]大于a[2]則交換兩者的值,否則不變。再比較a[2]與a[3]的值,若a[2]大于a[3]則交換兩者的值,否則不變。再比較a[3]與a[4],以此類推,最后比較a[n-1]與a[n]的值。這樣處理一輪后,a[n]的值一定是這組數據中最大的。再對a[1]~a[n- 1]以相同方法處理一輪,則a[n-1]的值一定是a[1]~a[n-1]中最大的。再對a[1]~a[n-2]以相同方法處理一輪,以此類推。共處理n-1輪后a[1]、a[2]、……a[n]就以升序排列了。 優點:穩定; 缺點:慢,每次只能移動相鄰兩個數據。 二、選擇排序 每一趟從待排序的數據元素中選出最小(或最大)的一個元素,順序放在已排好序的數列的最后,直到全部待排序的數據元素排完。 選擇排序是不穩定的排序方法。 n個記錄的文件的直接選擇排序可經過n-1趟直接選擇排序得到有序結果: ①初始狀態:無序區為R[1..n],有序區為空。 ②第1趟排序 在無序區R[1..n]中選出關鍵字最小的記錄R[k],將它與無序區的第1個記錄R[1]交換,使R[1..1]和R[2..n]分別變為記錄個數增加1個的新有序區和記錄個數減少1個的'新無序區。 …… ③第i趟排序 第i趟排序開始時,當前有序區和無序區分別為R[1..i-1]和R(1≤i≤n-1)。該趟排序從當前無序區中選出關鍵字最小的記錄R[k],將它與無序區的第1個記錄R交換,使R[1……i]和R分別變為記錄個數增加1個的新有序區和記錄個數減少1個的新無序區。 這樣,n個記錄的文件的直接選擇排序可經過n-1趟直接選擇排序得到有序結果。 優點:移動數據的次數已知(n-1次); 缺點:比較次數多。 三、插入排序 已知一組升序排列數據a[1]、a[2]、……a[n],一組無序數據b[1]、 b[2]、……b[m],需將二者合并成一個升序數列。首先比較b[1]與a[1]的值,若b[1]大于a[1],則跳過,比較b[1]與a[2]的值,若b[1]仍然大于a[2],則繼續跳過,直到b[1]小于a數組中某一數據a[x],則將a[x]~a[n]分別向后移動一位,將b[1]插入到原來a[x]的位置這就完成了b[1]的插入。b[2]~b[m]用相同方法插入。(若無數組a,可將b[1]當作n=1的數組a) 優點:穩定,快; 缺點:比較次數不一定,比較次數越少,插入點后的數據移動越多,特別是當數據總量龐大的時候,但用鏈表可以解決這個問題。 四、縮小增量排序 由希爾在1959年提出,又稱希爾排序(shell排序)。 已知一組無序數據a[1]、a[2]、……a[n],需將其按升序排列。發現當n不大時,插入排序的效果很好。首先取一增量d(d 優點:快,數據移動少; 缺點:不穩定,d的取值是多少,應取多少個不同的值,都無法確切知道,只能憑經驗來取。 五、快速排序 快速排序是冒泡排序的改進版,是目前已知的最快的排序方法。 已知一組無序數據a[1]、a[2]、……a[n],需將其按升序排列。首先任取數據a[x]作為基準。比較a[x]與其它數據并排序,使a[x]排在數據的第k位,并且使a[1]~a[k-1]中的每一個數據a[x],然后采用分治的策略分別對a[1]~a[k-1]和a[k+1]~a[n]兩組數據進行快速排序。 優點:極快,數據移動少; 缺點:不穩定。 六、箱排序 已知一組無序正整數數據a[1]、a[2]、……a[n],需將其按升序排列。首先定義一個數組x[m],且m>=a[1]、a[2]、……a[n],接著循環n次,每次x[a]++。 優點:快,效率達到O(1)缺點:數據范圍必須為正整數并且比較小 七、歸并排序 歸并排序是多次將兩個或兩個以上的有序表合并成一個新的有序表。最簡單的歸并是直接將兩個有序的子表合并成一個有序的表。 歸并排序是穩定的排序.即相等的元素的順序不會改變.如輸入記錄1(1) 3(2) 2(3) 2(4) 5(5) (括號中是記錄的關鍵字)時輸出的1(1) 2(3) 2(4) 3(2) 5(5)中的2和2是按輸入的順序。這對要排序數據包含多個信息而要按其中的某一個信息排序,要求其它信息盡量按輸入的順序排列時很重要.這也是它比快速排序優勢的地方. 歸并排序:歸并排序是一種非就地排序,將需要與待排序序列一樣多的輔助空間。在使用它對兩個己有序的序列歸并,將有無比的優勢。其時間復雜度無論是在最好情況下還是在最壞情況下均是O(nlog2n)。對數據的有序性不敏感。若數據節點數據量大,那將不適合。但可改造成索引操作,效果將非常出色。 堆排序:由于它在直接選擇排序的基礎上利用了比較結果形成。效率提高很大。它完成排序的總比較次數為O(nlog2n)。它是對數據的有序性不敏感的一種算法。但堆排序將需要做兩個步驟:-是建堆,二是排序(調整堆)。所以一般在小規模的序列中不合適,但對于較大的序列,將表現出優越的性能。 1. 概述 排序算法是計算機技術中最基本的算法,許多復雜算法都會用到排序。盡管各種排序算法都已被封裝成庫函數供程序員使用,但了解排序算法的思想和原理,對于編寫高質量的軟件,顯得非常重要。 本文介紹了常見的排序算法,從算法思想,復雜度和使用場景等方面做了總結。 2. 幾個概念 (1)排序穩定:如果兩個數相同,對他們進行的排序結果為他們的相對順序不變。例如A={1,2,1,2,1}這里排序之后是A = {1,1,1,2,2} 穩定就是排序后第一個1就是排序前的第一個1,第二個1就是排序前第二個1,第三個1就是排序前的第三個1。同理2也是一樣。不穩定就是他們的順序與開始順序不一致。 (2)原地排序:指不申請多余的空間進行的排序,就是在原來的排序數據中比較和交換的排序。例如快速排序,堆排序等都是原地排序,合并排序,計數排序等不是原地排序。 總體上說,排序算法有兩種設計思路,一種是基于比較,另一種不是基于比較。《算法導論》一書給出了這樣一個證明:“基于比較的算法的最優時間復雜度是O(N lg N)”。對于基于比較的算法,有三種設計思路,分別為:插入排序,交換排序和選擇排序。非基于比較的`排序算法時間復雜度為O(lg N),之所以復雜度如此低,是因為它們一般對排序數據有特殊要求。如計數排序要求數據范圍不會太大,基數排序要求數據可以分解成多個屬性等。 3. 基于比較的排序算法 正如前一節介紹的,基于比較的排序算法有三種設計思路,分別為插入,交換和選擇。對于插入排序,主要有直接插入排序,希爾排序;對于交換排序,主要有冒泡排序,快速排序;對于選擇排序,主要有簡單選擇排序,堆排序;其它排序:歸并排序。 3.1 插入排序 (1) 直接插入排序 特點:穩定排序,原地排序,時間復雜度O(N*N) 思想:將所有待排序數據分成兩個序列,一個是有序序列S,另一個是待排序序列U,初始時,S為空,U為所有數據組成的數列,然后依次將U中的數據插到有序序列S中,直到U變為空。 適用場景:當數據已經基本有序時,采用插入排序可以明顯減少數據交換和數據移動次數,進而提升排序效率。 (2)希爾排序 特點:非穩定排序,原地排序,時間復雜度O(n^lamda)(1 < lamda < 2), lamda和每次步長選擇有關。 思想:增量縮小排序。先將序列按增量劃分為元素個數近似的若干組,使用直接插入排序法對每組進行排序,然后不斷縮小增量直至為1,最后使用直接插入排序完成排序。 適用場景:因為增量初始值不容易選擇,所以該算法不常用。 3.2 交換排序 (1)冒泡排序 特點:穩定排序,原地排序,時間復雜度O(N*N) 思想:將整個序列分為無序和有序兩個子序列,不斷通過交換較大元素至無序子序列首完成排序。 適用場景:同直接插入排序類似 (2)快速排序 特點:不穩定排序,原地排序,時間復雜度O(N*lg N) 思想:不斷尋找一個序列的樞軸點,然后分別把小于和大于樞軸點的數據移到樞軸點兩邊,然后在兩邊數列中繼續這樣的操作,直至全部序列排序完成。 適用場景:應用很廣泛,差不多各種語言均提供了快排API 3.3 選擇排序 (1)簡單選擇排序 特點:不穩定排序(比如對3 3 2三個數進行排序,第一個3會與2交換),原地排序,時間復雜度O(N*N) 思想:將序列劃分為無序和有序兩個子序列,尋找無序序列中的最小(大)值和無序序列的首元素交換,有序區擴大一個,循環下去,最終完成全部排序。 適用場景:交換少 (2) 堆排序 特點:非穩定排序,原地排序,時間復雜度O(N*lg N) 思想:小頂堆或者大頂堆 適用場景:不如快排廣泛 3.4 其它排序 (1) 歸并排序 特點:穩定排序,非原地排序,時間復雜度O(N*N) 思想:首先,將整個序列(共N個元素)看成N個有序子序列,然后依次合并相鄰的兩個子序列,這樣一直下去,直至變成一個整體有序的序列。 適用場景:外部排序 4. 非基于比較的排序算法 非基于比較的排序算法主要有三種,分別為:基數排序,桶排序和計數排序。這些算法均是針對特殊數據的,不如要求數據分布均勻,數據偏差不會太大。采用的思想均是內存換時間,因而全是非原地排序。 4.1 基數排序 特點:穩定排序,非原地排序,時間復雜度O(N) 思想:把每個數據看成d個屬性組成,依次按照d個屬性對數據排序(每輪排序可采用計數排序),復雜度為O(d*N) 適用場景:數據明顯有幾個關鍵字或者幾個屬性組成 4.2 桶排序 特點:穩定排序,非原地排序,時間復雜度O(N) 思想:將數據按大小分到若干個桶(比如鏈表)里面,每個桶內部采用簡單排序算法進行排序。 適用場景:0 4.3 計數排序 特點:穩定排序,非原地排序,時間復雜度O(N) 思想:對每個數據出現次數進行技術(用hash方法計數,最簡單的hash是數組!),然后從大到小或者從小到大輸出每個數據。 使用場景:比基數排序和桶排序廣泛得多。 5. 總結 對于基于比較的排序算法,大部分簡單排序(直接插入排序,選擇排序和冒泡排序)都是穩定排序,選擇排序除外;大部分高級排序(除簡單排序以外的)都是不穩定排序,歸并排序除外,但歸并排序需要額外的存儲空間。對于非基于比較的排序算法,它們都對數據規律有特殊要求 ,且采用了內存換時間的思想。排序算法如此之多,往往需要根據實際應用選擇最適合的排序算法。 【排序算法的算法思想和使用場景總結】相關文章: 關于kmeans算法報告總結05-09 績效工資的算法01-14 失業保險的算法06-20 計算機算法和顯示方法的分析04-01 辭退員工補償的算法03-03 年假加班工資的算法01-14 曠工扣工資的算法01-23 《乘法的結合律和簡便算法》 教學設計04-13 《分數除法的意義和計算法則》教學設計03-17 分數除法的意義和計算法則教學設計03-17排序算法的算法思想和使用場景總結2
排序算法的算法思想和使用場景總結3