簡單選擇排序和直接插入排序
簡單選擇排序
簡單選擇排序就是通過關鍵字之間的比較,在記錄裏面找到最小(或者最大)的數字,並同當前位置交換之。
貼個代碼:
void SelectSort(SqList *L) { int i, j, min; for (i = 0; i < L->length - 1; i++) { min = i; for (j = i + 1; j < L->length; j++) { if (L->r[min] > L->r[j]) { min= j; } } if (i != min) swap(L, i, min); } }
分析一下:很顯然,對於一個無序數組來說,把第一個數的下標暫且作為值最小的下標,然後通過與其後的數據對比,找出真正的最小的數組的下標,如果找到,就交換,如果沒找到,說明當前數據是最小的,那麽就不用交換。然後下標遞增,再次比較。就這樣實現排序。
復雜度分析:
我們知道,交換最多需要n - 1次(最少需要0次)。而第i次排序需要n - i 次比較,那麽總共有 (n - 1) + (n - 2) + (n - 3) +..... + 1 = n * (n - 1) / 2次比較,顯然時間復雜度就是O(n ^ 2)(但是比起冒泡排序來說,簡單選擇的性能還是要比冒泡好一點。
直接插入排序
直接插入排序,就是將一個記錄插入到已經排好序的有序表中,從而得到一個新的有序表。
先給出代碼,稍後分析:
void InsertSort(SqList *L) { int i, j; for (i = 2; i < L->length; i++) //下標從2開始。 { if ( L->r[i] < L->r[i - 1]) { L->r[0] = L->r[i]; for (j = i - 1; L->r[j] > L->r[0]; j--) L->r[j + 1] = L->r[j]; L->r[j + 1] = L-> r[0]; //註意上面有j--,所以這裏空出來的位置應該是j + 1 } }
代碼分析:如上(升序排序),我們舉個栗子,有一個無序數組{5, 3, 2, 4 , 6},現在要把它給拍好,怎麽做呢?
首先,我們把r[1] = 5當作是有序的一個數組(這裏的L->r[0]必須要空出來當哨兵),即:{ 5 };那麽現在我們需要將剩下的{3, 2, 4, 6}插入到{5}這個有序表中,顯然現在的問題就是插入到5左邊還是右邊了,為此,下標從2開始,循環比較兩兩之間的大小,如果後者比前者小,那麽就把後者的值賦值給哨兵,再把前者適當的往後移動(這裏的適當是有條件的,也就是L->r[j] > L->r[0],即到出現比哨兵小的數據為止)。移動完之後再把哨兵的值賦值給移動出來的空位。
復雜度分析:如果要排序的數組一開始就是有序的,那麽只需要比較次數,時間復雜度為O(n),而最壞的情況(數組完全逆序),那麽這個時候,當外循環等於2(總共執行n - 2次)時,內循環執行了n - 1次,當外循環等於3時,執行了n - 2次。。。。。。所以,總的執行次數為 n - 2 + n - 3 + ....+ 1 = ( n-1) * (n - 2) / 2,也就是O(n^2)。雖然是平方階,但是它的性能比冒泡和簡單選擇要好的多。
以上。
下次寫希爾排序和堆排序
簡單選擇排序和直接插入排序