插入排序的測試及優化

2021-08-20 13:45:29 字數 3561 閱讀 3194

關於o(n^2) 的排序演算法中,插入排序是不得不提的一種。相比較於氣泡排序,選擇排序這些真正的o(n^2)演算法,插入演算法在一些情況下的效能會比一些高階排序演算法如歸併排序,快速排序更加高效,而這些情況我們會在下面的一些情況中進行討論。

首先,既然要寫乙個插入排序演算法,我們第乙個要做的自然是理解插入排序的過程是怎麼樣的。

第一步,給定乙個隨機產生的陣列,從第二個數進行遍歷;

第二步,將遍歷到的數與前乙個數進行比較,如果這個數小於前乙個數,則進行交換,再與前面的數進行比較,若小於,則再交換,一直比較到第乙個數;

第三步,如果遍歷的數大於前乙個數,不交換,繼續向後遍歷;

**示例:

public classinsertionsort 

elsebreak;}}

}

public static voidswap(object arr,intx,inty)
}
可能有同學要問了,你那個sort(comparable arr)是什麼意思呢?

其實,這裡是可以寫成sort(int arr),這樣就好理解了,就是乙個int型別的陣列嘛。

但是,我們排序的不可能永遠是乙個int型別的陣列,有可能我們需要排序浮點型的陣列,有可能我們需要根據學生的成績來對學生進行排名......

所以,我們就不能使用普通的比較arr[j]

classstudentimplementscomparable

@override

public intcompareto(student o)

}

這樣的話,我們寫的排序演算法就可以用來比較學生的成績了,這裡我們就不用關心comparato()裡面具體的方法是什麼,反正我們知道裡面是排序的規則,而這裡的規則就是學生的成績直接的比較。

注意:這樣的話,我們如果要比較乙個int型別的陣列,就不能直接用int型別,而要用integer(int的包裝類)型別的陣列,因為只有integer型別實現了comparable介面,可以用compareto()方法。

這樣一來,原版的插入排序就寫完了。這裡我們用來寫乙個testsort()方法,和乙個輔助類來建立乙個10000條資料的隨機數組,看看對這個陣列進行排序需要多長的時間。

public static voidtestsort(comparable arr)
system.currenttimemillis()用來獲取當前時間,單位為ms。在執行程式的前後獲取,再相減,則得到了程式執行的具體時間。

建立乙個輔助類來建立隨機數組:

public classsorttesthelper 

returnarr;

}public static voidprintarray(object arr)

system.out.println();}}

generaterandomarray(int n, int l, int r) : n是陣列的長度,[l , r]是資料的取值範圍。我們用這個方法來建立陣列。

完整的程式如下:

public classinsertionsort 

elsebreak;}}

}public static voidsort(comparable arr,intl,intr)

arr[j] = e;}}

public static voidmain(string args)

public static voidtestsort(comparable arr)

public static voidswap(object arr,intx,inty)

}

執行結果如下:

我們可以看到,僅僅是10000條資料,我們就用了15.841s。這簡直是不可忍受的,我們僅僅是10000條資料,資料範圍在[1,1000],就讓插入排序花了16秒的時間,簡直是災難。

自然的,我們就會生出這樣一種想法,能不能讓插入排序進行優化呢?讓他更加快速呢?

答案是肯定的。

public static voidsort(comparable arr,intl,intr)

arr[j] = e;}}

這種優化的思想就是爭取讓交換的次數降低,讓賦值的次數降低。每次找到較小的數時,並不將他與前面的數交換,而是記錄下來,將前一位的值賦值給他,一直到遇見了比他小的數或者是第一位數,則將遍歷的數賦值為較小的數。

降低了一些,需要10.831秒,比原來的演算法優化了30%左右。

而值得一提的是,插入演算法在進行大量相同數字排序和近似有序數字排序時,其耗費的時間會大大降低,讓我們來做個測試,首先在我們的輔助類中新增乙個近似有序陣列:

public staticinteger generatenearlyorderarray(intn,intswaptimes)

for(inti=0; iintposx = (int)math.random()*n;

intposy = (int)math.random()*n;

integer temp = arr[posy];

arr[posy] = arr[posx];

arr[posx] = temp;

}returnarr;

}

進行測試:

public static voidmain(string args)
驚呆了有沒有,這次只花了0.004s。這說明在近似有序陣列進行排序時,插入排序的效率比起o(nlogn)的高階演算法還要高效,而關於大量重複資料的排序同學們也可以自己去進行測試。

關於插入排序及優化

了解了插入排序,一般插入排序是這樣的 class array1 list a selectsort a list a public static void selectsort int arr public static void list int arr system.out.println 這樣...

插入排序優化

插入排序的是十分常見的o n 2 級別的排序演算法,其排序思路如下 一次迴圈使前n個數都為有序,巢狀的二次迴圈將第n個數插入到前n個數中合適的位置,我的實現 如下 public void insertsort int a,int n else 這個插入排序相對於選擇排序有可以提前結束一層迴圈的特點,...

插入排序 python實現及優化

原理 通過構建有序序列,對於未排序的資料,在已排序的序列中,從後向前掃瞄,找到相應位置並插入。python實現步驟 1 預設把第乙個元素看作有序序列。2 從第二個元素開始遍歷,依次將元素與上乙個元素比較,如果小於,則將上乙個元素向後挪乙個位置 如果相等,位置想對不變。3 繼續與上上乙個位置的元素比較...