【排序演算法】——希爾排序、快速排序
希爾排序
演算法描述:
1)先取定一個小於 n 的整數 gap1 作為第一個增量,把整個序列分成 gap1 組。
所有距離為 gap1 的倍數的元素放在同一組中,在各組內分別進行排序(分組內採用直接插入排序或其它基本方式的排序)。
2)然後取第二個增量gap2<gap1,重複上述的分組和排序。
3)依此類推,直至增量gap=1,即所有元素放在同一組中進行排序為止。
簡單來說:
就好像上體育課,大家亂糟糟的站在一起,老師讓大家排成一排然後按照1~4 (gap1)報數,讓數到同一個數字的同學按大小個排序,排完之後在按1~3報數,然後重複上面的排序規則。
程式碼:
//希爾排序
private static void shellSort(int[] a) {
//進行分組,初始的gap=n/2,然後遞減知道n=1;
for(int gap=(a.length+1)/2;gap>0;){
//分組冒泡
for(int i=0;i<a.length-gap;i++){
//組內排序
for
if (a[j]>a[j+gap]) {
swap(a, j, j+gap);
}
}
}
if (gap>1) {
gap=(gap+1
}else if (gap==1) {
break;
}
}
}
演算法分析:
開始時 gap 的值較大, 子序列中的元素較少, 排序速度較快。
隨著排序進展, gap 值逐漸變小, 子序列中元素個數逐漸變多,由於前面大多數元素已基本有序, 所以排序速度仍然很快。
分組後n值減小,n²更小,而T(n)=O(n²),所以T(n)從總體上看是減小了。
Gap的取法有多種。 shell 提出取 gap = n/2 ,gap = gap/2 ,…,直到gap = 1。gap若是奇,則gap=gap+1
快速排序
演算法特點:
以某個記錄為界(該記錄稱為支點或樞軸),將待排序列分成兩部分:
①一部分: 所有記錄的關鍵字大於等於支點記錄的關鍵字
②另一部分: 所有記錄的關鍵字小於支點記錄的關鍵字
程式碼
public static void quickSort(int a[],int p,int r){
if (p<r) {
int q = partition(a,p,r);
quickSort(a, p, q-1);
quickSort(a, q+1, r);
}
}
private static int partition(int[] a, int p, int r) {
int i=p;//第一個元素的樞軸
int j = r+1;
int x = a[p];
while(true){
while(a[++i]<x&&i<r);
while(a[--j]>x);
if (i>=j) {
break;
}
swap(a, i, j);
}
swap(a, p, j);
return j;
}
private static void swap(int[]a,int i,int j) {
int temp;
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
演算法分析:
快速排序是一個遞迴過程,快速排序的趟數取決於遞迴樹的高度。
如果每次劃分對一個記錄定位後, 該記錄的左側子序列與右側子序列的長度相同,
則下一步將是對兩個長度減半的子序列進行排序, 這是最理想的情況。
要是一次看不懂程式碼也不要著急~
先試著理解一下演算法的思想
再來看看程式碼