【數據結構與算法之美】十大排序思路及代碼實現

1.冒泡排序

1.1 實現思路

冒泡排序思想是通過將兩個互相相鄰的元素進行比較,如果前一個元素大於後一個元素,進行交換位置。否則不交換。外層循環控制層數,內存循環控制個數。每進行一輪都會將最大數字移動到最後,所以經過多次交換就可以實現將數組中的元素進行有序排列了。

note:我們在內存循環中加入一個判斷標誌 如果當前內存循環沒有進行交換數據的操作 說明這個數組的元素已經是有序的 就可以退出循環操作。

1.2 代碼實現

public static void bubbleSort(int [] arr){
        for (int i = 0; i < arr.length-1; i++) {
            boolean flag = true;
            for (int j = 0; j < arr.length-1-i; j++) {
                if (arr[j]>arr[j+1]){
                    int temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = temp;
                    flag = false;
                }
            }
            if (flag){
                break;
            }
        }
    }

2.選擇排序

2.1 實現思路:

選擇排序主要每次選擇一個最小的下標值,在內層循環中找到最小值下標,循環n次找到最小值。最後將預先尋找的值與最小下標值進行交換,每次選擇一個最小的。多次循環就可以將一個無序的數組轉換成一個有序的數組了。

2.2 代碼實現

   public static void selectSort2(int[] arr) {
            for (int i = 0; i < arr.length - 1; i++) {
                int minIndex = i;
                for (int j = i + 1; j < arr.length; j++) {
                    if (arr[j] < arr[minIndex]) {
                        minIndex = j;
                    }
                }
                int temp = arr[minIndex];
                arr[minIndex] = arr[i];
                arr[i] = temp;
            }
        }

3.插入排序

3.1 實現思路:

插入排序的思想是 將數組中分爲已排好序 和
未拍好序兩部分。第一個是已經拍好序的。所以i從1開始每次選擇一個元素,插入到已排好序當中。而內層循環所作的就是找到判斷當前要插入的元素應該插入的位置。如此反覆執行,就可以找到應當插入的位置。

3.2 代碼實現

   public static void selectSort2(int [] arr){
            for (int i = 1; i < arr.length; i++) {
                int value = arr[i];
                int j = i-1;
                for (; j >=0 ; j--) {
                    if (arr[j]>value){
                        arr[j+1] = arr[j];//care
                    }else {
                        break;
                    }
                }
                arr[j+1] = value;//care
            }
        }

4.歸併排序

4.1 實現思路

歸併排序:使用遞歸思想,將一個無序的數組多次分割成多個小的數組,將小的數組進行元素比較 最小的元素放在前面,反覆執行就可以實現數組排序了

4.2 代碼實現

   public static void mergeSorts(int[] arr) {
            mergesort(arr, 0, arr.length - 1);
        }
    
        private static void mergesort(int[] arr, int p, int r) {
            if (p >= r) return;
    
            int q = p + (r - p) / 2;
    
            //合併左邊
            mergesort(arr, p, q);
            //合併右邊
            mergesort(arr, q + 1, r);
    
            merge(arr, p, q, r);
    
        }
    
        private static void merge(int[] arr, int p, int q, int r) {
    
            int i = p;
            int j = q + 1;
            int count = 0;
            //定義一個數組
            int[] tmp = new int[r - p + 1];
            //合併兩個數組
            while (i <=q && j<=r) {
                if (arr[i] < arr[j]) {
                    tmp[count++] = arr[i++];
                } else {
                    tmp[count++] = arr[j++];
                }
            }
    
            int start = i;
            int end = q;
            if (j <= r) {//注意邊界條件
                start = j;
                end = r;
            }
    
            //轉移剩餘的元素
            while (start <= end) {
                tmp[count++] = arr[start++];
            }
            //迴歸arr
            for (int k = 0; k <= (r - p); k++) {
                arr[p+k] = tmp[k];
            }
        }

4.3 簡潔版

 private static void mergeSort(int[] array, int left, int right) {
            //條件判斷
            if (right <= left) {
                return;
            }
            //中間下標位置
            int mid = (left + right) >> 1;
    
            //左邊排序
            mergeSort(array, left, mid);
            //右邊排序
            mergeSort(array, mid + 1, right);
            //合併
            merge(array, left, mid, right);
        }
    
        private static void merge(int[] array, int left, int mid, int right) {
            //臨時數組
            int[] temp = new int[right - left + 1];
    
            int i = left, j = mid + 1, p = 0;
    
            //比較大小 後存儲
            while (i <= mid && j <= right) {
                temp[p++] = array[i] <= array[j] ? array[i++] : array[j++];
            }
            //剩餘的存儲
            while (i <= mid) {
                temp[p++] = array[i++];
            }
    
            while (j <= right) {
                temp[p++] = array[j++];
            }
    
            //賦值給原來的數組
            for (int k = 0; k < temp.length; k++) {
                array[left + k] = temp[k];  //care
            }
        }

5.快速排序

5.1 實現思路

如果要在排序數組中下標從p到r之間的一組數據,我們選擇p到r之間的任意一個數據作爲一個piovt(分區點),我們遍歷p到r之間的數據,將小於piovt的放到左邊,將大於piovt的放到右邊,將piovt放到中間,經過這一步驟之後,數組p到r之間的數據就被分成了三部分,前面是p到q-1之間是小於piovt,中間是piovt
後面的q+1到r之間的是大於piovt。

5.2 代碼實現

   private static void quickSort(int[] arr, int start, int end) {
            if(end <= start){
                return;
            }
    
            int piovt = partition(arr,start,end);//獲取到piovt下標
            quickSort(arr,start,piovt-1); 
            quickSort(arr,piovt+1,end);
        }
    
        private static int partition(int[] arr, int start, int end) {
            //piovt 標杆位置, counter 小於piovt的元素的個數
            int piovt = end;
            int counter = start;
            for (int i = start; i < end; i++) {
                if (arr[i]<arr[piovt]){  //如果小於Arr[piovt] 移動到piovt前面 否則不動
                    int temp = arr[counter];
                    arr[counter] = arr[i];
                    arr[i] = temp;
                    counter++;
                }
            }
            int temp  = arr[piovt];
            arr[piovt] = arr[counter];
            arr[counter] = temp;
            return counter;
        }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章