1. 程式人生 > >各種排序演算法思想即實現

各種排序演算法思想即實現

下面的演算法都會給出例子與分析,只寫主要思想,有不懂的或者覺得我寫的有錯誤可以留言,我都會關注的,謝謝~
選擇排序:

public void selectSort(int[] a) {       
    for(int i = 0;i<a.length-1;i++){
        int k = i;
        for(int j = i;j<a.length;j++){
            if(a[j]<a[k]){
                k = j;
            }
        }
        int min = a[i];
        a[i] = a[k];
        a[k] = min
; } }

原始陣列: 5 3 16 6 9
第1次遍歷: 3 5 16 6 9
第2次遍歷: 3 5 16 6 9
第3次遍歷: 3 5 6 16 9
第4次遍歷: 3 5 6 9 16
每次在後面選擇最小的一個與前面的數交換即可,前面的都是排好序的

插入排序:

public void insertSort(int[] a){
    for(int i = 1;i<a.length;i++){
        int num = a[i];
        for(int j = i-1;j>=0;j--){
            if
(num<a[j]){ a[j+1] = a[j]; }else{ a[j+1] = num; break; } if(j==0){ a[0] = num; } } } }

原始陣列: 5 3 16 1 9
第1次遍歷: 3 5 16 1 9
第2次遍歷: 3 5 16 1 9
第3次遍歷: 1 3 5 16

9
第4次遍歷: 1 3 5 9 16
就像起牌一樣,每次把小牌往前面插,這樣前面的數總是排序好的。

快速排序:

public int partition(int[] a,int low,int high){
    int key = a[low];
    while(low<high){
        while(a[high]>=key&&high>low){
            --high;
        }
        a[low] = a[high];
        if(low<high){
            low++;
        }
        while(a[low]<=key&&high>low){
            ++low;
        }
        a[high] = a[low];
        if(low<high){
            high--;
        }
    }
    a[low] = key;
    return low;
}

public void qSort(int[] a,int s,int t){
    if(s<t){
        int privotkey = partition(a, s, t);
        qSort(a, s, privotkey-1);
        qSort(a, privotkey+1, t);
    }
}

public void quickSort(int[] a){
    qSort(a, 0, a.length-1);
}

原始陣列: 49 38 65 97 76 13 27 49
第1次partition: 27 38 13 49 76 97 65 49
第2次partition: 13 27 38 49 76 97 65 49
第3次partition: 13 27 38 49 49 65 76 97
第4次partition: 13 27 38 49 49 65 76 97
利用分治法的思想,以陣列的第low個數為分界線,讓陣列的左邊都小於a[low],右邊都大於a[low]、

歸併排序:

public static void mergeSort(int[] data) {  
    sort(data, 0, data.length - 1);  
}  

public static void sort(int[] data, int left, int right) {  
    if (left >= right)  
        return;  
    int center = (left + right) / 2;   
    sort(data, left, center);  
    sort(data, center + 1, right);  
    merge(data, left, center, right);  
    print(data);  
}  
public static void merge(int[] data, int left, int center, int right) {  
    int[] tmpArr = new int[data.length];  
    int mid = center + 1;  
    int third = left;  
    int tmp = left;  
    while (left <= center && mid <= right) {  
        if (data[left] <= data[mid]) {  
            tmpArr[third++] = data[left++];  
        } else {  
            tmpArr[third++] = data[mid++];  
        }  
    }    
    while (mid <= right) {  
        tmpArr[third++] = data[mid++];  
    }  
    while (left <= center) {  
        tmpArr[third++] = data[left++];  
    }   
    while (tmp <= right) {  
        data[tmp] = tmpArr[tmp++];  
    }  
}  

利用分治法的思想,把陣列分成兩個子陣列,把每個子陣列都排好序,然後把它們合併成一個組。

計數排序:

private static void sort(int a[], int b[], int k)  
{  
    //初始化計數陣列  
    int c[] = new int[k];  
    for(int i = 0; i<k; i++)  
        c[i] = 0;  
    //計算陣列中重複的次數  
    for(int i=0; i<a.length; i++)  
    {  
        c[a[i]] = c[a[i]]+1;  
    }  
    for(int i = 1; i<k; i++)  
    {  
        c[i] = c[i]+c[i-1];  
    }  
    //將a陣列中的元素按照順序複製到b中  
    for(int i = a.length-1; i>=0; i--)  //如果是從0到a.length,結果正確,相同元素逆序
    {  
        b[c[a[i]]-1] = a[i];  
        c[a[i]] = c[a[i]]-1;  
    }  
    for (int i = 0; i < c.length; i++) {
        System.out.println(c[i]);
    }
}  

對負數排序的擴充套件思路:計數排序要求元素能夠作為陣列的下標,自然不能是負數。我的思路是先把負數和非負數分離開來,對負數取絕對值,再對這兩組數分別計數排序,最後再把兩組數合併可以了。時間複雜度依舊是O(n),只是n會大一點。當然處理的都是整數。

基數排序:

public static int countDigit(int[] array) {
    //求最大數的位數
    int max = array[0];
    for (int i = 1; i < array.length; i++) {
        if (array[i] > max) {
            max = array[i];
        }
    }
    int time = 0;
    while (max > 0) {
        max /= 10;
        time++;
    }
    return time;
}

private static void radixSort(int[] array,int radix, int distance) {  
     //array為待排序陣列              array
     //radix,代表基數                   10
     //distance代表排序元素的位數        7

     int length = array.length;  
     int[] temp = new int[length];//用於暫存元素  
     int[] count = new int[radix];//用於計數排序  
     int divide = 1;  
     System.out.println("distance"+distance);
     for (int i = 0; i < distance; i++) {  
         System.arraycopy(array, 0,temp, 0, length);  
         Arrays.fill(count, 0);  
         for (int j = 0; j < length; j++) {  
             int tempKey = (temp[j]/divide)%radix;  
             count[tempKey]++;  
         }  
         for (int j = 1; j < radix; j++) {  
             count [j] = count[j] + count[j-1];  
         }  
         //個人覺的運用計數排序實現計數排序的重點在下面這個方法              
         for (int j = length - 1; j >= 0; j--) {  
             int tempKey = (temp[j]/divide)%radix;  
             count[tempKey]--;  
             array[count[tempKey]] = temp[j];  
         }  
         divide = divide * radix;                  
     }            
 }  

基數排序就是按照關鍵字排序。常規的思維是先排高位數,排完高位數再排低位數。這樣的話假如排三位數,那麼排完百位再排十位的時候要考慮百位數是否相等,將大桶裡分成了很多小桶,增加了難度,所以應該先從低位排起。