相關文章
演算法(一)時間複雜度
演算法(二)初等排序前篇[插入和希爾排序]
1.選擇排序
根據上一篇文章講到的插入排序和希爾排序,我們把選擇排序的陣列也分為已排序部分和未排序部分。
圖解選擇排序
在用圖來講解選擇排序之前,我們要先了解選擇排序的規則。
選擇排序的規則
就是重複執行以下的處理:
1.找出未排序部分最小值的位置min。
2.將min位置的元素與未排序部分的起始元素做對比,如果順序錯誤則將它們進行就交換。
以陣列a={5,4,8,7,9,3,1}為例,我們對其進行從小到大排序,排序過程如下圖所示。
首先我們找到未排序部分最小的值a[6]=1和未排序的起始元素a[0]=5相比較,發現a[6]的值更小,則將兩個數進行交換,以此類推。
最終得到的結果為a={1,3,4,5,7,8,9}
實現選擇排序
接下來要實現插入排序,針對下圖來定義變數。
如上圖所示,i為迴圈變數,代表未排序部分的開頭元素; j為迴圈變數,用來遍歷未排序部分找出最小值min。
接下來我們用程式碼來實現選擇排序,如下所示。
public class SelectionSort {
public static void main(String[] args) {
int a[] = {5, 4, 8, 7, 9, 3, 1};
ArrayUtils.printArray(a);
int b[] = selection(a);
ArrayUtils.printArray(b);
}
public static int[] selection(int[] a) {
int i, j, min, v;
int n = a.length;
for (i = 0; i < n; i++) {
//每次將未排序部分的首元素下標賦值給下標min
min = i;
//得到未排序部分的最小值的下標並賦值給min
for (j = i+1; j < n; j++) {
if (a[j] < a[min]) {
min = j;
}
}
v = a[i];
a[i] = a[min];
a[min] = v;
}
return a;
}
}複製程式碼
其中負責列印陣列的ArrayUtils類如下所示。
public class ArrayUtils {
public static void printArray(int[] array) {
System.out.print("{");
int len=array.length;
for (int i = 0; i < len; i++) {
System.out.print(array[i]);
if (i < len - 1) {
System.out.print(", ");
}
}
System.out.println("}");
}
}複製程式碼
輸出結果為:
{5, 4, 8, 7, 9, 3, 1}
{1, 3, 4, 5, 7, 8, 9}
選擇排序複雜度
假設資料總數為n,則為了搜尋未排序部分最小的的值需要(n-1)+(n-2)+(n-3)+……+1次比較,也就是n²/2+n/2次比較,因此時間複雜度為O(n²)。同樣的,此前講過的插入排序和氣泡排序的時間複雜度也是O(n²)。它們的區別就是:不含flag的冒泡演算法和選擇排序並不依賴於比較運算的次數,不受輸入資料的影響,而插入演算法卻依賴於比較運算的次數,處理某些資料時會具有很高的效率。
2.氣泡排序
氣泡排序應該是開發者最容易理解的排序演算法,它的基本思想就是每次比較兩個相鄰的元素,如果它們的順序錯誤就把它們交換過來。需要進行排序的元素則向水中的氣泡一樣慢慢的移向水面。
圖解氣泡排序
與選擇排序一樣,需要進行氣泡排序的陣列也分為已排序部分和未排序部分。
氣泡排序的規則為:從陣列末尾開始依次比較相鄰的兩個元素,如果大小關係相反則交換位置,直到陣列中不再有順序相反的相鄰元素。
我們對陣列 a={5,3,2,4,1} 進行從小到大排序,排序過程如下所示。
第一輪排序:
我們將陣列末尾的a[4]的值和a[3]的值進行對比,發現a[4]的值比a[3]的值小,則將它們交換,再接著對剩下的相鄰的兩個元素進行對比和交換,最終得到的結果為a={1,5,3,2,4},已排序的部分的元素為1。
第二輪排序:
首先對比a[3]和a[4]的值,發現a[3]的值比a[4]的值小,則不需要進行排序。最終得到的結果為a={1,2,5,3,4},已排序部分的元素為1、2。
第三輪排序:
經過第三輪排序,已排序部分的元素為1、2、3。
第四輪排序:
經過四輪排序我們最終得到的結果為a={1,2,3,4,5}
實現氣泡排序
實現插入排序時,我們要先定義兩個變數,i為迴圈變數,表示未排序部分的開頭元素,從陣列開頭向末尾移動。j也為迴圈變數,用於對未排序部分中相鄰元素兩兩比較,從陣列的末尾n-1開始減小到 i 結束(i=1)。
程式碼實現如下所示。
public class BubbleSort {
public static void main(String[] args) {
int a[] = {5, 3, 2, 4, 1};
ArrayUtils.printArray(a);
int b[] = bubble(a);
ArrayUtils.printArray(b);
}
public static int[] bubble(int[] a) {
int i, j, v;
int n = a.length;
for (i = 1; i <= n - 1; i++) {
for (j = n - 1; j >= i ; j--) {
if (a[j] < a[j - 1]) {
v = a[j];
a[j] = a[j - 1];
a[j - 1] = v;
}
}
}
return a;
}
}複製程式碼
其中ArrayUtils的printArray方法此前講過,這裡就不再給出,列印結果為:
{5, 3, 2, 4, 1}
{1, 2, 3, 4, 5}
氣泡排序的複雜度
最壞的情況下,氣泡排序對未排序部分的相鄰元素進行了(n-1)+(n-2)+(n-3)+……+1次比較,也就是n²/2-n/2次比較,根據推導大O階的規則我們得出氣泡排序的時間複雜度為O(n²)。
歡迎關注我的微信公眾號,第一時間獲得部落格更新提醒,以及更多成體系的Android相關原創技術乾貨。
掃一掃下方二維碼或者長按識別二維碼,即可關注。