嚴重聲明:此貼轉自http://www.cnblogs.com/FlyingBread/archive/2007/01/27/631830.html ,轉寄請註明出處。
交換排序,插入排序和選擇排序都是很簡單也很基礎的排序演算法。在世面上各種各樣的演算法和資料結構的書中都很輕易地找的到他們的蹤影。在這兒寫出來不外乎是加深自己的印象,也為有需要的朋友做一個參考。
1 交換排序
交換排序是一種很簡單的排序方法。其主要思想如下:
(1)利用要排序範圍中的第0個資料d[i]與範圍中其它資料d[j]相比較。如果前面的資料比後面大,那麼就交換這兩個資料(就是把較小的資料放在第0個位置)。然後再和排序範圍內下一個資料d[j+1]相比較。依此類推。
(2)當執行完步驟(1)後,最小值即位於範圍中的第0個位置。然後在剩下的資料中找到一個最小的,放在第1個位置,這樣迴圈尋找下去直到所有資料結束,最後可以得到由小到大的排序結果。
交換排序的思想和冒泡排序的思想很類似,實現的代碼也非常相似。下面是一個簡單的說明例子。
假設要排序的資料是:6 2 5 1 3 4
步驟一:
因為6>2,所以2和6交換
2 6 5 1 3 4
步驟二:因為2<5,所以不交換
2 6 5 1 3 4
步驟三:因為2>1,所以交換
1 6 5 2 3 4
步驟四:因為1<3,所以不交換
1 6 5 2 3 4
步驟五:因為1<4,所以不交換
1 6 5 2 3 4
這樣我們叫找到了最小值1,按照同樣的辦法,就可以找到第二個,第三個最小值。。完成排序。
實現代碼非常簡單,如下所示:
/// <summary>
/// 交換排序的思想非常簡單,從第一個資料開始,在剩下的資料中找
/// 比它小的資料,如果找到了,就交換兩者。
/// 第一次尋找可以找到最小的資料,和第0個資料交換
/// 第二次在剩下的n-1個資料中尋找,找個最小的和第一個資料交換
/// 依次交換剩下的所有資料使之有序
/// </summary>
/// <param name="myArray"></param>
public static void ExchangeSort(int [] myArray)
{
int i, j;
for(i=0; i<myArray.Length-1; i++) //從第0個資料開始
{
for(j=i+1; j<myArray.Length; j++)//在剩下的資料中迴圈
{
if(myArray[j] < myArray[i]) //如果有比它小的,交換兩者
{
Swap(ref myArray[j], ref myArray[i]);
}
}
}
}
2 選擇排序
選擇排序也是很簡單的排序方法之一。其主要思想如下:
(1)第一次在數組中尋找出最小的值a[i],將其和第0個位置交換。
(2)此時剩下n-1個值,同樣從中找出最小的值a[j],a[j]和第一個資料交換
(3)重複上面的步驟,在剩下的範圍中找出最小的值和最小數組下標的值進行交換。
一般會設定一個額外變數small來記錄最小值的下標,以便於在迴圈之後,交換指定位置和最小值位置的值。根據上面的描述,我們可以很容易地就寫出選擇排序的演算法。
/// <summary>
/// 選擇排序的中心思想是每次都從未排序的資料中選出最小的資料,
/// 和未排序資料的第一個資料交換。
/// 第一次選出最小的資料放在第0個位置
/// 第二次在剩下的n-1個資料中選出最小的資料放在第一個位置
/// 依次下去,將所有資料排序
/// </summary>
/// <param name="myArray"></param>
public static void SelectSort(int [] myArray)
{
int i, j, small;
for(i=0; i<myArray.Length-1; i++) //資料起始位置,從0到倒數第二個資料
{
small = i; //記錄最小資料的下標
for(j=i+1; j<myArray.Length; j++) //在剩下的資料中尋找最小資料
{
if(myArray[j] < myArray[small])
{
small = j; //如果有比它更小的,記錄下標
}
}
Swap(ref myArray[i], ref myArray[small]); //將最小資料和未排序的第一個資料交換
}
}
3 插入排序
插入排序也是一種原理非常簡單的排序方法,屬於插入方法的排序。其主要思想如下:
(1)首先從第一個資料開始,將該值插入到其前面已經排好序的資料當中。插入的位置是第一個大於該資料的記錄的前面。如果沒有大於它的資料,就將其放在排好序的資料的最後。由於現在排序尚未開始,因此只有第1個元素。
(2)接著是第二個元素,用步驟1的方法插入到大於它的數的前面。現在第一個,第二個資料都是有序的了。
(3)依次可以排第三個,第四個資料,直到所有的資料完全排好序。可以從下面例子看出詳細的過程。
還是假設要排序的數字為:6 2 5 1 3 4
步驟1:移動第一個
6 2 5 1 3 4
步驟2:移動第二個,因為2<6,所以將2放在6前面
2 6 5 1 3 4
步驟3:移動第三個,因為2<5<6,所以將5放在6前面
2 5 6 1 3 4
步驟4:移動第四個,因為1<2<5<6,所以將1放在最前面
1 2 5 6 3 4
步驟5:移動第五個,因為2<3<5<6,所以將3放在2後面
1 2 3 5 6 4
步驟6:移動第六個,因為3<4<5<6,所以將4將在3後面
1 2 3 4 5 6
這樣所有的資料就都排好序了。
其實現的演算法如下:
/// <summary>
/// 插入排序的中心思想在於將未排序的資料插入一個有序表中
/// 第一次將第一個資料放入一個有序表中,該有序表只有一個資料
/// 第二次將第二個資料插入有序表中,使之小的在前,大的在後
/// 第三次將第三個資料插入有序表中
/// 依次下去,將所有資料放入有序表中
/// </summary>
/// <param name="myArray"></param>
public static void InsertSort(int[] myArray)
{
int i, j, temp;
for(i=1; i<myArray.Length; i++)
{
temp = myArray[i]; //儲存當前資料
j = i-1;
//將資料插入有序表中,如果表中的資料比該資料大,
//那麼就依次向後移動有序表中的資料,直到找到第一個比它小的資料,
//將它放在那個資料後面
while(j>=0 && myArray[j]>temp)
{
myArray[j+1] = myArray[j];
j--;
}
myArray[j+1] = temp; //將資料插入有序表中
}
}
4 效率比較
在實現這三種演算法以後,這三種演算法都是O(n^2)的演算法。效率並不高。還是做個小小的實驗來驗證一下效率,還是使用1+1中的隨機數來測試,可以得到下表,看到這幾種演算法的效率區別。單位為毫秒
|
500隨機數 |
5000隨機數 |
20000隨機數 |
| 基本冒泡 |
1.5625 |
160.9375 |
2457.8125 |
| 交換排序 |
1.5625 |
118.75 |
1895.3125 |
| 選擇排序 |
1.5625 |
68.75 |
1081.25 |
| 插入排序 |
1.5625 |
34.375 |
543.75 |
從上面的表格中可以看到,插入排序比其餘的幾種排序方法快得多。在資料量越大的時候越明顯。還有更快的排序方法嗎?答案是肯定的。