1. 程式人生 > >java-排序演算法-未完

java-排序演算法-未完

再java中經常需要對資料進行排序,一個好的排序演算法,可以大大提高程式的效率,最近開始看資料結構與演算法,將自己學習的筆記和心得紀錄下來。

  1. 氣泡排序

    這大概是想我這種新手使用最多的排序方法了,也基本上是唯一能熟練使用的排序演算法,但是在時間上可以說是相當慢了。由於這個比較簡單,原理什麼的都不重要了,忽略。

     private static void sortByBubble(Integer[] array) {
            Date date = new Date();
            for (int i = 0; i < array.length - 1; i++) {
                for (int j = i + 1; j < array.length; j++) {
                    if (array[i] > array[j]) {
                        int m = array[j];
                        array[j] = array[i];
                        array[i] = m;
                    }
                }
            }
            Date end = new Date();
            long l = (end.getTime() - date.getTime());
            System.out.println("用時:" + l + "毫秒");
        }

     

  2. 選擇排序
    假設第一個為最小值,並用變數min記錄下標,從下一個開始和這個比較,如果比它小,則將min換為這個數的下標,
    一輪迴圈結束,則交換一個位置,開始第二輪,這樣雖然比較次數依然是 n*n /2,但交換的次數從O(N*N) 減少到了O(N),在數量比較大時,相比冒泡,速度就會有明顯的提升。
    private static void sortByChoose(Integer[] array) {
            Date date = new Date();
            int min;
            for (int i = 0; i < array.length; i++) {
                min = i;
                for (int j = i + 1; j < array.length; j++) {
                    if (array[j] < array[min]) {
                        min = j;
                    }
                }
                int m = array[i];
                array[i] = array[min];
                array[min] = m;
            }
            Date end = new Date();
            long l = (end.getTime() - date.getTime());
            System.out.println("選擇排序用時:" + l + " 毫秒");
        }

     

  3. 選擇排序的優化
    有上面可以推出優化版本,我們直接同時將最大和最小都找出來,這樣就能減少一般的迴圈次數。
     private static void sortByChoose2(Integer[] array) {
            Date date = new Date();
            int min, max;
            for (int i = 0; i < array.length >> 1; i++) {
                min =  i;
                max = array.length - 1 - i;
                for (int j = i + 1; j < array.length - i ; j++) {
                    if (array[j] < array[min]) {
                        min = j;
                    }
                    if(array[j] > array[max]){
                        max = j;
                    }
                }
    
                int s = array[i];
                array[i] = array[min];
                array[min] = s;
                int m = array[array.length - 1 - i];
                array[array.length - 1 - i] = array[max];
                array[max] = m;
            }
            Date end = new Date();
            long l = (end.getTime() - date.getTime());
            System.out.println("選擇排序2用時:" + l + " 毫秒");
        }

    上面三個在資料量為:150000 條的時間

  4. 插入排序
    預設左邊都是已經排好序的,接下來就是將右邊的數一個一個的插到已經排好的序列中。
    首先需要一個臨時變數存放即將插入的這個數,然後依次從有序部分右邊開始向左比較,如何該數一直大/小,則持續移動陣列,直到找到應該插入的位置。這個表述有些繞,我們還是看程式碼,或者直接看書《資料結構與演算法》
    private static void sortByInsert(Integer[] array) {
            print(array);
            Date date = new Date();
            for (int i = 1; i < array.length; i++) {
                int temp = array[i]; //存放帶插入的數
                int foot; // 應該插入位置的下標
                // 從有序部分的最右邊開始查詢 temp 的存放位置
                for (foot = i; foot > 0; foot--) {
                    // 如果上一個 大於 temp ,則將陣列右移一位
                    if (array[foot - 1] > temp) {
                        array[foot] = array[foot - 1];
                    } else {
                        break;
                    }
                }
                //將該數放到合適的位置
                array[foot] = temp;
            }
            Date end = new Date();
            long l = (end.getTime() - date.getTime());
            print(array);
            System.out.println("插入排序用時:" + l + " 毫秒");
        }

    當然我們也可以換一個寫法,讓程式碼看起來更簡潔
     

    private static void sortByInsert2(Integer[] array) {
            print(array);
            Date date = new Date();
            for (int i = 1; i < array.length; i++) {
                int temp = array[i]; //存放帶插入的數
                int foot = i; // 應該插入位置的下標
                while (foot > 0 && array[foot - 1] > temp) {
                    array[foot] = array[foot - 1];
                    foot -- ;
                }
                //將該數放到合適的位置
                array[foot] = temp;
            }
            Date end = new Date();
            long l = (end.getTime() - date.getTime());
            print(array);
            System.out.println("插入排序用時:" + l + " 毫秒");
        }

    思考:既然左邊是有序的,那麼在查詢是為何還要這樣一個一個的遍歷呢?後面會介紹的,在有序的陣列中查詢是,我們還有很多方式優化,比如常見的二分查詢,這樣速度將進一步提高,但我們就現在也能看出插入排序的效率了

  5. 待續