排序的总结

排序总结

前言:排序的知识从很早以前就学了,但一直记的不是很牢固,所以今天就把主要的排序都做一些整理,以后需要用到的时候可以进行快速回忆。以下的所有讨论都是基于非递减排序的。

冒泡排序

流程:每次都进行相邻元素的对比,如果前一个数字大于后一个数字,则进行交换,之后对每一对元素都进行相同的操作,经过一轮扫描之后最大的元素就被放置在最后一个元素。然后再从头进行同样的流程,只是接下来扫描的截止位置减少了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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章