首先看一下各大排序演算法的時間空間複雜度:
1.快速排序
偽**如下
void quick_sort (int a, int p, int r)
}
其中,partion()函式是重點,主要思想如下圖。
注意:返回值是位置(下標),因為快排是就地排序,所以函式引數為原來陣列,輸出還是原來陣列(排好序)。
上圖的主要在於:1)遞迴函式終止條件p;
2)用i,j來記錄每次排序乙個元素後,大於key和小於關鍵字的尾部位置。
理解以上兩點程式設計很容易,此處略。
2.氣泡排序
關鍵:每次兩兩比較,不滿足不等式,則交換位置(由此可知是雙重for迴圈解決問題),所以每次只能選出乙個最大(或者最小)。理解原理後,**也很簡單,略。示意例子如下:
原始待排序陣列| 6 | 2 | 4 | 1 | 5 | 9 |
第一趟排序(外迴圈)
第一次兩兩比較6 > 2交換(內迴圈)
交換前狀態| 6 | 2 | 4 | 1 | 5 | 9 |
交換後狀態| 2 | 6 | 4 | 1 | 5 | 9 |
第二次兩兩比較,6 > 4交換
交換前狀態| 2 | 6 | 4 | 1 | 5 | 9 |
交換後狀態| 2 | 4 | 6 | 1 | 5 | 9 |
第三次兩兩比較,6 > 1交換
交換前狀態| 2 | 4 | 6 | 1 | 5 | 9 |
交換後狀態| 2 | 4 | 1 | 6 | 5 | 9 |
第四次兩兩比較,6 > 5交換
交換前狀態| 2 | 4 | 1 | 6 | 5 | 9 |
交換後狀態| 2 | 4 | 1 | 5 | 6 | 9 |
第五次兩兩比較,6 < 9不交換
交換前狀態| 2 | 4 | 1 | 5 | 6 | 9 |
交換後狀態| 2 | 4 | 1 | 5 | 6 | 9 |
第二趟排序(外迴圈)
第一次兩兩比較2 < 4不交換
交換前狀態| 2 | 4 | 1 | 5 | 6 | 9 |
交換後狀態| 2 | 4 | 1 | 5 | 6 | 9 |
第二次兩兩比較,4 > 1交換
交換前狀態| 2 | 4 | 1 | 5 | 6 | 9 |
交換後狀態| 2 | 1 | 4 | 5 | 6 | 9 |
...第三趟排序(...)
第四趟排序(外迴圈)無交換
第五趟排序(外迴圈)無交換
排序完畢,輸出最終結果1 2 4 5 6 9
3.希爾(shell)排序
希爾排序shell sort是基於插入排序
的一種改進,同樣分成兩部分,
第一部分,希爾排序介紹
第二部分,如何選取關鍵字,選取關鍵字是希爾排序的關鍵
第一塊希爾排序介紹
準備待排陣列[6 2 4 1 5 9]
首先需要選取關鍵字,例如關鍵是3和1(第一步分成三組,第二步分成一組),那麼待排陣列分成了以下三個虛擬組:
[6 1]一組
[2 5]二組
[4 9]三組
看仔細啊,不是臨近的兩個數字分組,而是3(分成了三組)的倍數的數字分成了一組,
就是每隔2個數取乙個,每隔2個再取乙個,這樣取出來的數字放到一組,
把它們當成一組,但不實際分組,只是當成一組來看,所以上邊的"組"實際上並不存在,只是為了說明分組關係
對以上三組分別進行插入排序
變成下邊這樣
[1 6] [2 5] [4 9]
具體過程:
[6 1]6和1交換變成[1 6]
[2 5]2與5不動還是[2 5]
[4 9]4與9不動還是[4 9]
第一趟排序狀態演示:
待排陣列:[6 2 4 1 5 9]
排後陣列:[1 2 4 6 5 9]
第二趟關鍵字取的是1,即每隔0個取乙個組成新陣列,實際上就是只有一組啦,隔一取一就全部取出來了嘛
此時待排陣列為:[1 2 4 6 5 9]
直接對它進行插入排序
還記得插入排序
怎麼排不(就是玩撲克插入牌)?複習一下
[1 2 4]都不用動,過程省略,到5的時候,將5取出,在前邊的有序陣列裡找到適合它的位置插入,就是4後邊,6前邊
後邊的也不用改,所以排序完畢
順序輸出結果:[1 2 4 5 6 9]
第二塊希爾排序的關鍵是如何取關鍵字,因為其它內容與插入排序一樣
增量的取值規則為第一次取總長度的一半,第二次取一半的一半,依次累推直到1為止,剛從下文中看到的這一段描述,感謝!
3.選擇排序:
選擇排序的思想非常直接,不是要排序麼?那好,我就從所有序列中先找到最小的,然後放到第乙個位置。之後再看剩餘元素中最小的,放到第二個位置……以此類推,就可以完成整個的排序工作了。可以很清楚的發現,選擇排序是固定位置,找元素。相比於插入排序的固定元素找位置,是兩種思維方式。不過條條大路通羅馬,兩者的目的是一樣的。
4.歸併排序
原理:將原序列劃分為有序的兩個序列,然後利用歸併演算法進行合併,合併之後即為有序序列。
要點:歸併、分治(分治很簡單,注意終止條件,合併是重點)
void mergesort(node l, int m, int n)
}
5.基排序原理:將數字按位數劃分出n個關鍵字,每次針對乙個關鍵字進行排序,然後針對排序後的序列進行下乙個關鍵字的排序,迴圈至所有關鍵字都使用過則排序完成。
要點:對關鍵字的選取(先排低位,後排高位),元素分配收集。
6.堆排序
堆排序其實也是一種選擇排序,是一種樹形選擇排序。只不過直接選擇排序中,為了從r[1...n]中選擇最大記錄,需比較n-1次,然後從r[1...n-2]中選擇最大記錄需比較n-2次。事實上這n-2次比較中有很多已經在前面的n-1次比較中已經做過,而樹形選擇排序恰好利用樹形的特點儲存了部分前面的比較結果,因此可以減少比較次數。
堆排序的重點:就地排序,
下標的推算關係(下面的例子都是堆頂下標為1開始)
parent(i)
return |_ i/2 _|;
left(i)
return 2*i;
right(i)
return 2*i + 1;
給定乙個陣列a[1...n];則
a[( |_ n/2 _| +1)...n]
全是樹中的葉子。明白以上兩點很重要,下面介紹保持堆的性質:
void max_heapify(int *a, int heap_size, int i) //i 為待處理保持性質的結點下標
if(r < heap_size && a[largest] < a[r]) //右孩子數值大
if(largest != i)
}
基本思路,從下標i開始,比較a[i],left[i]和right[i],選出最大的值作為父節點,被交換的子節點再一次迭代(如果沒有進行交換,演算法停止)。
有了保持堆的性質,則對堆的每乙個非葉子節點,從下往上呼叫max_heapify則就建立乙個堆。
void build_max_heap(int *a, int array_size, int heap_size)
}
建立了堆後,就可以進行堆排序了:根節點和堆尾節點(葉子)交換位置,然後呼叫max_heapify,重複這個過程。 資料結構1 排序
就算複習再緊張,也要動手實踐資料結構中的基本演算法,徹底理解演算法的本質。不要讓任何理由成為不程式設計的藉口。從快速排序開始,將演算法問題一一攻克。複習提綱 基本資料結構 棧和佇列,陣列和鍊錶 樹和二叉樹 二叉查詢樹 平衡二叉樹 雜湊表 排序演算法 選擇排序 氣泡排序和快速排序 堆和堆排序 計數排序...
資料結構 07 排序
簡單的排序方法 氣泡排序 選擇排序 插入排序 希爾排序。先進的排序方法 歸併排序 快速排序 堆排序 基數排序。1.演算法思想 每次在未排序的元素中兩兩比較找最大值,邊找邊從後往前儲存 未排序.第i大 第2大 第1大 一般情況,整個氣泡排序只需進行 k 1 k氣泡排序結束的條件是 在某一趟排序過程中沒...
資料結構7 排序
理解選擇排序的不穩定性 選擇排序 氣泡排序 插入排序 public int charusort int intarr for int i 1 i intarr.length i return intarr 正確性檢測 test public void sorttest system.out.prin...