1. 程式人生 > >【排序演算法】——希爾排序、快速排序

【排序演算法】——希爾排序、快速排序

希爾排序

演算法描述:

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

(int j=i;j<a.length-gap;j+=gap){
         if (a[j]>a[j+gap]) {
           swap(a, j, j+gap);
         }  
       }
     }
     if (gap>1) {
       gap=(gap+1
)/2;
     }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;  
 }


演算法分析:

快速排序是一個遞迴過程,快速排序的趟數取決於遞迴樹的高度。

如果每次劃分對一個記錄定位後, 該記錄的左側子序列與右側子序列的長度相同, 

則下一步將是對兩個長度減半的子序列進行排序, 這是最理想的情況。



要是一次看不懂程式碼也不要著急~

先試著理解一下演算法的思想

再來看看程式碼