排序的總結

排序總結

前言:排序的知識從很早以前就學了,但一直記的不是很牢固,所以今天就把主要的排序都做一些整理,以後需要用到的時候可以進行快速回憶。以下的所有討論都是基於非遞減排序的。

冒泡排序

流程:每次都進行相鄰元素的對比,如果前一個數字大於後一個數字,則進行交換,之後對每一對元素都進行相同的操作,經過一輪掃描之後最大的元素就被放置在最後一個元素。然後再從頭進行同樣的流程,只是接下來掃描的截止位置減少了1個。
代碼實現:

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

選擇排序

流程:第一次從待排序的數字中選擇最小的元素,與數組的起始位置進行交換,然後再從接下來的待排序數字中繼續尋找最小的元素,與已排序數組的後一個序列進行交換,依此類推。因爲每次都將最小的元素插入到已排序數組的後面,所以最後一定能把數組排好序。

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

選擇排序是O(n ^ 2)的排序算法中唯一一個不穩定的排序,所以通常是最差的選擇。

插入排序

流程:插入排序每次都將一個數字插入到一個已經排序好的數組裏面,然後繼續遍歷數組,找到每個數字在前面排好序的數組中正確的位置。

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

注意插入排序的時間複雜度會受到數據狀況的影響,因爲每次插入數據的時候,前面的數組已經排好序了,如果這個數字比前面的所有數字都大,那麼就不需要進行插入操作了。如1 2 3 4 5進行插入排序,時間複雜度只有O(1);如果是5 4 3 2 1的話,每一輪都要進行插入操作,時間複雜度是O(n)。

歸併排序

流程:將一個數組不斷二分,然後把二分的兩部分數組合併爲一個有序數組,這個有序數組可以跟另一對有序數組進行合併,最終就可以使整個數組變成有序數組了。

public class mergeSort {

    public static void mergeSort(int[] arr) {
        if (arr == null || arr.length == 0) {
            return;
        }
        mergeSort(arr, 0, arr.length - 1);
    }

    public static void mergeSort(int[] arr, int left, int right) {
        if (left >= right) {
            return;
        }
        int mid = left + ((right - left) >> 1);
        mergeSort(arr, left, mid);
        mergeSort(arr, mid + 1, right);
        merge(arr, left, mid, right);
    }

    public static void merge(int[] arr, int left, int mid, int right) {
        int[] help = new int[right - left + 1];
        int p1 = left;
        int p2 = mid + 1;
        int i = 0;
        while (p1 <= mid && p2 <= right) {
            help[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];
        }
        while (p1 <= mid) {
            help[i++] = arr[p1++];
        }
        while (p2 <= right) {
            help[i++] = arr[p2++];
        }
        for (i = 0; i < help.length; i++) {
            arr[left++] = help[i];
        }
    }
}

堆排序

思路:將數組先建立成一個大根堆,然後每次都將堆頂交換到堆尾,然後將堆的大小減去1,再將新的堆繼續調整爲大根堆,重複以上過程。

public class heapSort {

    public static void heapSort(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            heapInsert(arr, i);
        }

        int size = arr.length;
        swap(arr, 0, --size);

        while (size > 0) {
            heapify(arr, 0, size);
            swap(arr, 0, --size);
        }
    }

    public static void heapInsert(int[] arr, int i) {
        while (arr[i] > arr[(i - 1) / 2]) {
            swap(arr, i, (i - 1) / 2);
        }
    }

    public static void heapify(int[] arr, int i, int size) {
        int left = i * 2 + 1;
        while (left < size) {
            int largest = left + 1 < size && arr[left] < arr[left + 1] ? left + 1 : left;
            largest = arr[i] < arr[largest] ? largest : i;
            if (largest == i) {
                break;
            }
            swap(arr, i, largest);
            i = largest;
            left = i * 2 + 1;
        }
    }

    public static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}

快速排序

思路:快速排序是基於分區的過程的,將一個數字作爲分區的基準,經過一輪分區,會把小於該數的數字放到數字的左邊,大於該數的數字放在數字的右邊。然後基準數字就找到自己的位置,再對基準數字的左邊和右邊進行以上的遞歸操作,這樣每一輪分區之後,基準數字都會找到自己的位置,到最後就能把數組進行排序了。

桶排序

常見疑問

1.插入排序和選擇排序有什麼不同?

基於非遞增排序說明,插入排序是每次都跟前面相鄰的數字進行對比,如果小於的話則進行交換,否則進行下一輪插入查找。而選擇排序則是每次都找尋未排序數組中的最小數字去進行交換。

總結

發佈了34 篇原創文章 · 獲贊 3 · 訪問量 3846
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章