選擇,插入,冒泡,二分法,歸併,希爾排序算法合集演示及標註

1.選擇排序


理解核心思想,取出一個元素,在它後面的每一位中進行比較,選擇出一個最小/最大的元素,來與它交換。



代碼示例

//比較
    public static boolean less(int a, int b) {
        if (a > b)
            return true;
        return false;
    }
    //交換
    public static void exch(int[] num, int i, int j) {
        int temp = num[i];
        num[i] = num[j];
        num[j] = temp;
    }
    //排序
    public static void sort(int[] num) {
        for (int i = 0; i < num.length; i++) {
            int min = i;
            // 除開i座標的前面的元素
            for (int j = i + 1; j < num.length; j++)
                // 注意理解這裏兩個比較對象。
                // 後面的每一個元素與min座標比較。
                // 目的是找出比min座標還小/大的值
                if (less(num[j], num[min]))
                    min = j;
            // 進行交換
            exch(num, i, min);
        }
    }


總結

第一步,設置標記

比較出最小/最大

交換標記點下標與比較的元素。


2.插入排序


理解核心思想,取出一個元素,比較它之前的元素,進行兩兩交換。由於一開始就是這樣操作,保證了前面的數組具有有序性,從而進行交換後一樣保持有序。



代碼示例


//比較
    public static boolean less(int a, int b) {
        if (a > b)
            return true;
        return false;
    }

    //交換
    public static void exch(int[] num, int i, int j) {
        int temp = num[i];
        num[i] = num[j];
        num[j] = temp;
    }

    //排序
    public static void sort(int[] num) {
        for (int i = 0; i < num.length; i++) {
            //比較當前i,之前的元素,進行兩兩交換操作。(關鍵)
            for (int j = i; j > 0 && less(num[j], num[j - 1]); j--)
                exch(num, j, j - 1);
        }
    }


總結

比較兩兩元素,滿足條件交換。


3.快速排序(二分法排序)


理解核心思想,選取第一位作爲標記,經過一次排序後,將這個數組分爲兩個部分(無序的),左邊的小於標記,右邊的大於標記。選取第二位,重複上面操作。最終整個數組有序。


fd

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

    public static void sort(int[] num, int left, int right) {
        int pos;
        if (left < right) {
            //算出中間位置
            pos = pos(num, left, right);
            //以中間位置進行分割成兩部分
            sort(num, left, pos - 1);
            sort(num, pos + 1, right);
        }
    }

    public static int pos(int[] num, int left, int right) {
        int temp = num[left];
        while (left < right) {
            //右邊開始尋找,與標記點比較
            while (left < right && num[right] >= temp)
                right--;
            //發現比標記點小。將右邊的小值賦值給左邊,並且將左邊的下標向前移位。因爲下面代碼要從左邊搜索了。
            if (left < right)
                num[left++] = num[right];
            //左邊開始尋找,與標記點比較
            while (left < right && num[left] <= temp)
                left++;
            //發現比標記點大,將左邊的大值賦值給右邊,並且將右邊的下標--,因爲代碼要從右邊搜索了。
            if (left < right)
                num[right--] = num[left];
        }
        //最終完成,最後一步是左邊的值賦值給右邊,所以此時的left就處於中間位置。我們將標記點值賦值給它,
        num[left] = temp;
        //返回分割點。
        return left;
    }


    public static void main(String[] args) {
        int[] num = new int[20];
        Random random = new Random();
        for (int i = 0; i < 20; i++) {
            num[i] = random.nextInt(100);
        }
        sort(num);
        for (int i :
                num) {
            System.out.print(i + "\t");
        }
        System.out.println();
    }


總結

標記點

右邊小的賦值給左邊,左邊大的賦值給右邊

確定中間點,賦值標記點值,返回下標


4.希爾排序


理解核心思想,增量概念,每次在增量間比較,以及交換。縮小增量,重複比較,交換。利用的插入排序算法。

public void sort(int[] nums) {
        /** 結合了插入排序 **/
        /** 數字長度N **/
        int N = nums.length;
        /** 確認間隔長度 **/
        int h = 3;
        while (h < N / 3) h = 3 * h + 1;
        while (h >= 1) {
            /** 注意需要從i=h開始 i++ **/
            for (int i = h; i < N; i++)
            /** j=i開始 **/
                for (int j = i; j >= h && less(nums[j], nums[j - h]); j -= h)//插入排序
                    exch(nums, j, j - h);
            h = h / 3;
        }
    }


總結

理解快速排序,改變其增量即可。


5.歸併排序


理解核心思想,歸併排序,類似於分支法解決問題,將一個長度很長的數組,從中間分開,分成兩半,取一半,重複上述操作即可。最終變成長度爲2的數組,比較後,進行交換,在末端保持了有序性。繼而整體保持了有序性。


    /**
     * @param nums
     */
    public void sort(int[] nums) {
        sort(nums, 0, nums.length - 1);
    }

    public void sort(int[] nums, int low, int high) {
        int mid = low + (high - low) / 2;
        if (low < high) {
            /** 左邊排序 **/
            sort(nums, low, mid);
            /** 右邊排序 **/
            sort(nums, mid + 1, high);
            merge(nums, low, mid, high);
        }
    }

    private void merge(int[] nums, int low, int mid, int high) {
        int[] temp = new int[high - low + 1];
        int i = low;
        int j = mid + 1;
        int k = 0;
        /** 兩邊合併**/
        while (i <= mid && j <= high) {
            if (nums[i] < nums[j]) {
                temp[k++] = nums[i++];
            } else {
                temp[k++] = nums[j++];
            }
        }
        /** 左邊多餘的合併 **/
        while (i <= mid) {
            temp[k++] = nums[i++];
        }
        /**  右邊多餘的合併 **/
        while (j <= high) {
            temp[k++] = nums[j++];
        }
        /** 拷貝合併後的數到原數組 **/
        for (int k2 = 0; k2 < temp.length; k2++)
            nums[low + k2] = temp[k2];
    }

總結

實現末端長度爲2的數組,進行比較交換,保持了底層有序,進而整體有序。


 6.堆排序

理解核心思想,將數組理解成邏輯完全二叉樹結構。僅僅是邏輯結構,實際還是以數組形式保存。有邏輯關係式,父節點與子節點之間關係,p(i)=c(2*i+1)|c(2*i+2),很重要。

public static void sort(int[] n) {
        for (int i = 0; i < n.length; i++) {
            createMaxHeap(n, n.length - 1 - i);
            exch(n, 0, n.length - 1 - i);
        }
    }

    public static void createMaxHeap(int[] n, int lastIndex) {
        int pIndex = (lastIndex - 1) / 2;
        for (int i = pIndex; i >= 0; i--) {
            int k = i;
            while (2 * k + 1 <= lastIndex) {
                int cIndex = 2 * k + 1;
                if (cIndex < lastIndex)
                    if (n[cIndex] < n[cIndex + 1])
                        cIndex++;
                if (n[k] < n[cIndex]) {
                    exch(n, cIndex, k);
                    k = cIndex;
                } else {
                    //關鍵的,跳過,上一級父節點
                    break;
                }
            }
        }
    }

總結
堆排序,沒什麼的說的。自己跟着代碼邏輯,自己畫圖,理解,自然就理會了。一定要自己跟着代碼走一遍。化圖解。


7.計數排序

理解核心思想,統計每個元素出現的個數,然後以n-m有序數,來排序。(講起來有點難懂)

public static void sort(int[] n) {
        int max = n[0];
        int min = max;
        for (int i = 0; i < n.length; i++) {
            if (max < n[i])
                max = n[i];
            if (min > n[i])
                min = n[i];
        }

        int[] c = new int[max - min + 1];

        for (int i = 0; i < n.length; i++) {
            c[n[i] - min] += 1;
        }
        for (int i = 0, index = 0; i < max - min + 1; i++) {
            for (int j = 0; j < c[i]; j++) {
                n[index++] = i + min;
            }
        }
    }

總結
總結什麼呢?看代碼理會。不懂@我

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章