演算法學習之直接插入排序(java)

韶華無限發表於2014-10-14

直接插入排序每次從無序表中取出第一個元素,把它插入到有序表的合適位置,使有序表仍然有序。直接插入排序屬於穩定的排序。

根據對直接插入排序的理解,從後面無序的序列中取出第一個元素,然後跟前面的有序序列的元素一一對比,找到合適的位置k,然後它後面的元素後移一位,把該元素放在k的位置,實現方法如下:

public static void insertSort1(int src[]){
		if(src==null||src.length<2){
			return;
		}
		for(int i=1;i<src.length;i++){
			for(int k=0;k<i;k++){
				if(src[i]<src[k]){
					for(int j=k;j<i;j++){
						int temp=src[i];
						src[i]=src[j];
						src[j]=temp;
					}
				}
			}
		}
	}
使用10萬隨機資料測試,結果如下:

開始排序...
排序時間是10993毫秒
7,15,29,35,38,41,72,73,79,102,112,112,116,124,130,149,154,164,175,199,……,999973,999990,999993


以上實現是從有序序列的0位置向後找位置,然後使用了大量的賦值操作後移元素,消耗時間很長。另一種實現可以從有序序列的最後元素開始比較和交換,省去一輪兒後移的for迴圈,實現方法:

public static void insertSort2(int src[]){
		if(src==null||src.length<2){
			return;
		}
		for(int i=1;i<src.length;i++){
			
			for(int k=i;k>0;k--){
				if(src[k]>=src[k-1]){
					break;
				}
				int temp=src[k];
				src[k]=src[k-1];
				src[k-1]=temp;
			}
		}
	}
10萬隨機測試資料結果:

開始排序...
排序時間是4419毫秒
10,29,32,50,54,54,59,64,71,81,84,93,94,122,123,143,155,168,184,187,……,999975,999988,999990
可以看出比第一種實現速度快了很多,但是有沒有更快一些的實現呢?第二種方法中的每一步的元素後移都是通過交換完成的,是否可以先後移,最後一步找到合適的位置k時把待排元素temp放到k位置呢?即src[k]=temp。然後就有了第三種實現方法:

/**
	 * 插入排序:從未排序序列中選擇第一個元素與前面已排序序列中的元素比較,插入(交換到)到合適位置。
	 * 
	 * 思路:已排序的序列 src[0]~src[i],src[i+1]是未排序的第一項。s[i+1]的數值temp同src[i]比較,如果temp小,則src[i]向後移位,
	 * 		temp繼續與src[i-1]比較,以此類推,直到temp不小於src[i-x],此時 讓 src[i-x+1]=temp;一輪兒比較結束。
	 * 比較:與insertSort2方法比較,減少了交換賦值次數。
	 * 100000陣列排序 2.9s級別。
	 * @param src
	 */
	public static void insertSort3(int src[]){
		if(src==null||src.length<2){
			return;
		}
		for(int i=1;i<src.length;i++){
			int temp=src[i];
			if(src[i-1]<src[i]){
				continue;
			}
			int pos=i;
			for(int k=i;k>0;k--,pos=k){
				if(src[k-1]>temp)
					src[k]=src[k-1];
				else
					break;
			}
			src[pos]=temp;
		}
	}
繼續10萬隨機測試資料排序:

開始排序...
排序時間是2937毫秒
10,22,26,34,51,52,55,62,86,95,95,119,125,140,147,156,159,167,168,175,……,999968,999974,999998
第三種實現速度又提升了一些。優化演算法就是要減少賦值操作。

以上就是簡單插入排序,如果要繼續優化插入排序,可以用希爾排序來實現。

相關文章