*****選擇排序*****數組
方法描述:首先找到第一個最小的數,和第一個數交換;而後從剩下的找出最小的與第二個交換,以此類推。
效率: 長度爲N的數組,大約N2/2比較,N次交換
特色: 1.運行時間和輸入無關,有序數組,所有相等的數組,隨機數組所用時間同樣,沒有充分利用輸入的初始狀態。
2.數據移動最少,與輸入成線性關係。
代碼: 測試
sort(int[] a){
int n = a.length;
for(int i = 0; i < n; i++){
int min = i;
for(int j = i; j < n; j++){
if(a[j] < a[i])
swap(a[i],a[j]);
}
}
}
*****插入排序*****spa
背景:打撲克牌
方法描述:後面的數插入到前面已經有序的子數組中
效率: 平均移動一半元素,因此N2/4次比較和交換;最壞N2/2次比較和交換;最好 N-1 次比較和0次交換
特色: 對於部分有序的數組效率很是高,時間是線性級別的。
幾個典型的部分有序數組:數組中每一個元素距離它的最終位置不遠;一個有序的大數組接一個小數組;數組中只有幾個元素的位置不正確;
代碼: 指針
sort(int[] a){
int n = a.length;
for(int i = 1; i < n; i++){
for(int j = i-1; j >= 0 && a[j] < a[i]; j--){
swap(a[i],a[j]);
}
}
}
*****希爾排序*****排序
背景:大規模的插入排序效率很低,由於它僅僅交換相鄰的元素。希爾排序的思想就是:對大數組中間隔爲h的子數組排序,將數組大約分紅
h個間隔爲h的子數組,並逐漸減少h,h=1時其實就是插入排序。這樣作的好處是,排序之初,只對間隔爲h的子數組排序,排序規模小,速度快;
隨着h的減少,數組趨於有序,此時插入排序能充分發揮做用。
方法描述:後面的數插入到前面已經有序的子數組中
效率: 平均移動一半元素,因此N2/4次比較和交換;最壞N2/2次比較和交換;最好 N-1 次比較和0次交換
特色: 對於部分有序的數組效率很是高,時間是線性級別的。
代碼: 遞歸
sort(int[] a){
int n = a.length;
int h = 1;
while(h < N/3) h = 3*h+1;
while(h >= 1){
for(int i = h; i < n; i++){
for(int j = i; j >= 0 && a[j] < a[i]; j -= h){
swap(a[j],a[i]);
}
}
h = h/3;
}
}
*****歸併排序*****it
方法描述:歸併思想
效率: NlogN
(1)原地歸併代碼:io
public static void merge(int[] a, int lo, int mid, int hi){
int i = lo, j = mid+1;
int[] aux = new int[a.length];
for(int k = lo; k <= hi; k++){
aux[k] = a[k];
}
for(int k = lo; k <= hi; k++){
if(i > mid) a[k] = aux[j++];//異常狀況必定要放前面,否則可能致使數組越界,報空指針異常
else if(j > hi) a[k] = aux[i++];
else if(a[i] < a[j]) a[k] = aux[i++];
else a[k] = aux[j++];
}
}
排序:效率
sort(int[] a, int lo, int hi){
if(hi < lo) return;
int mid = lo + (hi -lo)/2;
sort(a,lo,mid);
sort(a,mid+1,hi);
merge(a,lo,mid,hi);
}
改進:1.小規模用插入排序
2. 測試數組是否有序, a[mid] < a[mid+1] 就認爲有序,就跳過merge方法,這樣能使得有序的
子數組時間降爲線性。隨機數
(2)自底向上歸併排序:
方法:先兩兩歸併,再44歸併,再88,。。。。。
代碼:
sort(int[] a){
int n = a.length;
aux = new int[n];
for(int i = 1; i < n; i += i+i){
for(int j = 0; j< n-i; j+= i+i){
merge(a,j,j+i-1,Math.min(j+i+i-1,n-1));
}
}
}
特色:適合鏈表組織的數據,只須要從新組織鏈表連接就能將鏈表原地排序。
*****快速排序*****
特色:原地排序; nlogn; 內循環小,比較次數少,並且是和固定值進行比較,因此很是快. 例如歸併,插入排序,都會在內循環中移動元素,因此慢
和歸併排序相比:歸併是遞歸在前,處理數組在後;快排相反
代碼:
public static void sort(int[] a, int lo,int hi){
if(hi < lo) return;
int j = partition(a,lo,hi);
sort(a,lo,j-1);
sort(a,j+1,hi);
}
static partition(int[] a, int lo, int hi){
int i = lo, j = hi+1;
int guard = a[lo];
while(true){
while(a[++i] < guard) if(i == hi) break;
while(a[--j] > guard) if(j == lo) break;
if(i >= j) break;
swap(a[i],a[j]);
}
swap(a[lo],a[j]);
return j;
}
改進:基於插入排序對於小數組更加高效這一特色。 1. if(hi <= lo) return -> if(hi <= lo+M) {Insertion.sort(a,lo,hi); return;}