java排序
java排序之插入排序,插入排序分為直接插入排序和希爾排序兩種。
1.直接插入排序思想:在需要排序的一組數據中假設前該數組的前n-1(n >= 2)個數是已經排好序的,現在要把第n個數插入到前面的n-1個數中,使得這n個數也是排好順序的。如此反復進行,知道n等于需要排序的數組的長度時。就實現了該數組的直接插入排序。
代碼如下:
????/**
?*?
?* @param a 需要排序的數組
?*/
public static void simpleSort(int[] a){
for(int i = 1;i<a.length;i++){//外層for循環從1開始
int temp = a[i];
int j = i-1;
for(;j>=0 && temp < a[j];j--){
a[j+1] = a[j];
}
a[j+1] = temp;
}
}
//代碼解釋:
例如:需要排序的數組int[] a = {49,38,65,97,76,13,27};
第一次執行該方法執行for循環。
????i=1,temp=38,j=0,a[j]= 49 38 < 49 滿足for(;j>=0 && temp < a[j];j--)條件
????執行a[j+1] = a[j]即a[1] = a[0] 執行后數組為a=[49,49,65,97,76,13,27]?
執行j--,執行后j=-1 跳出內部for循環
執行a[j+1] = temp; j=-1 因此 a[0] = 38;
完成第一次循環后 數組a=[38,49,65,97,76,13,27]
?
第二次執行外部循環
i=2,temp=65,j=1,a[j]=49 65 > 49 不滿足內部for循環條件直接跳出
執行 a[j+1] = temp; 即a[2]=65
完成第二次循環后 數組a=[38,49,65,97,76,13,27]
?
第三次外部循環
i=3,temp=97,j=2,a[j]=65 97 > 65 不滿足內部for循環條件直接跳出
執行a[j+1] = temp;即a[3] = 97
完成第三次循環后 數組a=[38,49,65,97,76,13,27]
?
第四次外部循環
i=4,temp=76,j=3,a[j]=97 76 < 97 滿足內部for循環條件
執行a[j+1] = a[j];即a[4] = a[3] 執行后數組為a=[38,49,65,97,97,13,27]
執行j--,執行后j=2 a[j]=65 76 > 65 不滿足繼續執行內部for循環的條件 直接跳出
執行a[j+1] = temp;即a[3] = 76
完成第四次循環后 數組a=[38,49,65,76,97,13,27]
?
第五次外部循環
i=5,temp=13,j=4,a[j]=97 13 < 97 滿足內部for循環條件
執行a[j+1] = a[j];即a[5] = a[4] 執行后數組為a=[38,49,65,76,97,97,27]
執行j--,執行后j=3,a[j]=76 13 < 76 滿足內部for循環條件
執行a[j+1] = a[j];即a[4] = a[3] 執行后數組為a=[38,49,65,76,76,97,27]
執行j--,執行后j=2 a[j]=65 13 < 65 滿足內部for循環條件
執行a[j+1]=a[j];即a[3] = a[2] 執行后數組a=[38,49,65,65,76,97,27]
執行j--,執行后j=1 a[j]=49 13 < 49 滿足內部for循環條件
執行a[j+1]=a[j];即a[2]=a[1] 執行后數組為a=[38,49,49,65,76,97,27]
執行j--,執行后j=0,a[j] = 38,13 < 38 滿足內部for循環條件
執行a[j+1]=a[j];即a[1] = a[0] 執行后數組為a=[38,38,49,65,76,97,27]
執行j--,執行后j=-1,不滿足內部for循環條件跳出循環
執行a[j+1] = temp;即a[0]=13 執行后數組a=[13,38,49,65,76,97,27]
完成第五次循環 。
依次循環直到跳出外部for循環整個數組排序完成。
?
2.希爾排序法
?2.1實現思想 ??
? 在直接插入排序算法中,每次插入一個數。使有序序列 只增加幾個節點,而且對插入下一個數沒有提供任何幫助。如果比較相隔較遠(稱為增量)的兩個數,使得數移動時能跨過多個數,則進行一次比較就可能消除多個元素交換。D.L.Shell于1959年以他的名字命名的排序算法中實現了這一思想,這塊相關的java教程比較少。算法先將要排序的一組數按照某個增量d分成若干組,每組中元素的下標相差d。對每組中全部元素進行排序,然后在用一個較小的分量(較小的分量一般取當前分量的一半d/2)對排序后的的 整個數組進行分組。再對每組進行排序。當增量d=1時,整個要排序的數組本分成一個數組,然后進行排序,排序即可完成。
?2.2歷史背景
? 直接插入排序它的效率在某些時候是很高的,比如我們的元素本身就是基本有序的,我們只需要少量的插入操作,就可以完成整個數組的排序工作。此時直接插入很高效。還有就是數據比較少時,直接插入的優勢也比較明顯??蓡栴}在于兩個條件本身過于苛刻,現實中數據少和基本有序都屬于特殊情況。有條件當然是好的,條件不存在我們創造條件也要去做,于是科學家D.L.Shell研究出一種排序算法,對直接插入排序改進后可以提高效率。
? 如何然待排序的數據少呢?很容易想到就是將原本有大量數據的數組進行分組,分割成若干個子序列,此時每個子序列的數據就比較少。然后在這些子序列內分別進行直接插入排序,當整個序列都基本有序時,在對全體記錄進行一次直接插入排序。問題其實也就在這里,我們分隔待排序數組的目的就是為了減少數據的量,對每個子序列進行直接插入排序就是為了讓整個數組基本有序。
??例如數組a=[9,1,5,8,3,7,2,4,6]現在將他按前后順序分為三組a1=[9,1,5],a2=[8,3,7],
a3=[2,4,6],將三個子序列a1,a2,a3排序后重新組合在一起后a=[1,5,9,3,7,8,2,4,6],此時這個數組還是雜亂無序的,根本談不上基本有序,要排序還是直接重來一遍插入排序。這樣做只是瞎子戴眼鏡多余的圈圈,毫無用處,所謂基本有序不是局部有序而是小的數據基本在前面,大的的數據基本在后面,不大不小的數據基本在中間,因此我們會發現將一組需要排序的數據按照先后順序分組排序后滿足不了我們的要求。所以我們需要采取跳躍分割的策略:將相距某個“增量”的數據組成一個子序列,這樣才能保證在子序列內分別進行插入排序后得到的結果是一個基本有序的數組而不是一個局部有序的數組。
? ?代碼實現:
public static void shellSort(int[] a){
int j;
int len = a.length;
for(int d = len >> 1;d > 0;d = d >> 1 ){
for(int i = d;i<len;i++){
int temp = a[i];
for(j = i; j >= d && temp < a[j-d]; j -= d){
a[j] = a[j-d];
}
a[j] = temp;
}
}
}
轉載于:https://www.cnblogs.com/jinshiyill/p/5226474.html
總結
- 上一篇: jQuery 滚动条插件nicescro
- 下一篇: springboot : Failed