天天看點

數組常用排序算法排序算法總結

排序算法總結

常用排序算法

冒泡排序BubbleSort

直接選擇排序SelectSort

快速排序QuickSort

今天複習到數組部分,發現數組部分中比較重要的可能就是排序這個問題了。其他像周遊、填充替換數組元素、複制數組、查詢數組等都相對簡單,就把排序部分稍作整理。沒什麼高深知識,随便看看就好。

首先貼出冒泡排序和直接選擇排序的代碼,兩者相近且比較簡單,本來打算分着寫更明顯,不過看着實在太短了,就在一個類中寫出了,類名也沒改,大家将就看吧=。=

public class BubbleSort {//冒泡排序和直接選擇排序

    public static void main(String[] args) {
        int a[]=new int[]{,,,,};
        bubble(a);
        select(a);
    }
    public static void bubble(int arr[]){
        int temp;
        for(int i=;i<arr.length;i++){
            for(int j=;j<arr.length--i;j++){
                if(arr[j]>arr[j+]){
                    temp=arr[j+];
                    arr[j+]=arr[j];
                    arr[j]=temp;
                }
            }
        }
        for(int x:arr){
            System.out.print(x+" ");
        }
        System.out.println();
    }
    public static void select(int arr[]){

        for(int i=;i<arr.length;i++){
            int index = ;
            for(int j=;j<arr.length--i;j++){
                if(arr[index]<arr[j+]){
                    index=j+;
                }
            }
            int temp;
            temp=arr[arr.length--i];
            arr[arr.length--i]=arr[index];
            arr[index]=temp;
        }
        for(int x:arr){
            System.out.print(x+" ");
        }
    }
}
           

在我看來,冒泡排序和直接選擇排序相近。兩者的比較次數相同,交換次數:冒泡排序>直接選擇排序,代碼有一定的相似性。

兩者代碼都是有嵌套的兩層for循環作為主體,冒泡排序是相鄰兩數比較,若前者大于後者,則交換位置,直接選擇排序則是一輪循環下來用一個index标記此輪循環的最大值,然後在内層for循環結束後進行本輪最後一個位置和最大值的交換。

而快速排序和他們則有所差別。

public class QuickSort {
    public static void main(String[] args) {
        int arr[] = { , , , ,  };
        quickSort(arr, , arr.length - );
        //quick(arr,0,arr.length-1);
        for (int x : arr) {
            System.out.println(x);
        }
    }

    public static void quickSort(int arr[], int top, int end) {
        if (top < end) {
            int p = partition(arr, top, end);
            quickSort(arr, top, p);
            quickSort(arr, p + , end);
        }

    }

    public static int partition(int arr[], int top, int end) {//每次調用就完成一輪快排
        int x = arr[top];
        int i = top, j = end + ;
        while (true) {
            while (arr[++i] < x && i < end)//從左開始找到比top值大得數
                ;
            while (arr[--j] > x)//從右開始找到比top值小得數
                ;
            if (i >= j)//判斷兩個數是否相遇
                break;
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;//不相遇就交換兩個數
        }
        arr[top] = arr[j];
        arr[j] = x;
        return j;

    }
    public static void quick(int[] a, int left, int right){//sort函數源碼,
        for (int i = left, j = i; i < right; j = ++i) {//第一次進去時,i和j總相等
            int ai = a[i + ];//令ai=目前位置的下一個,記錄下新的要排序的數的值
            while (ai < a[j]) {//通過交換找到ai值在0-i+1範圍内應當在的位置,這不是快速排序,
                a[j + ] = a[j];
                if (j-- == left) {
                    break;
                }
            }
            a[j + ] = ai;//到此會發現i+1位之前都是從小到大排序,即每完成一輪循環,數組前面的數就多一個有序的。
        }
    }

}
           

快速排序則和他們完全不同。快速排序用到了分治思想,用遞歸算法達到将數組分割,簡化排序過程。

每一次調用quickSort()方法都會将目前數組分成三部分:首項、>首項、<首項。

分别在後兩個數組中再調用quickSort()方法,分割的下标則是由partition()方法決定的partition為“劃分”意,在這裡用來找到首項應該在的下标位置。

上述代碼中還出現了一個方法quick(),這個方法是從Arrays.sort()方法的源碼中找到的,一開始我認為是快速排序的一個非遞歸化變形,後來發現似乎不是如此,這個方法是從第一個數開始,不斷的往後擴充,沒添加一個數就找到這個數應當在的前面的位置,感覺類似直接選擇排序的倒叙版,但是他每一次又不會周遊整個數組,是以說我也拿不準究竟如何形容他,不過他玲珑的代碼段還是驚豔到我了,果然程式設計是一門藝術活,總有一些神奇的代碼片有着匪夷所思的用處。

如有不妥,敬請交流指教。