十大经典排序算法

首先排序算法可以分为内部排序算法和外部排序算法:在内存中进行的称为内部排序算法,也就是这里所说的这十种算法;相应的,当数据量很大时无法全部拷贝到内存需要使用外存,称为外部排序算法。接下来我们可用如下表来简单概括这十种算法:

表中数据说明:

  • 稳定:如果A原本在B前面,而A=B,排序之后A仍然在B的前面;
  • 不稳定:如果A原本在B的前面,而A=B,排序之后A可能会出现在B的后面;
  • 时间复杂度: 描述一个算法执行所耗费的时间;
  • 空间复杂度:描述一个算法执行所需内存的大小;
  • n:数据规模;
  • k:“桶”的个数;
  • In-place:占用常数内存,不占用额外内存;
  • Out-place:占用额外内存。

该十种排序算法可分为如下所示的两大类:

  • 比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序。
  • 非比较类排序:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此也称为线性时间非比较类排序。

在这里插入图片描述

冒泡排序(Bubble Sort)

算法步骤:

  1. 比较相邻的元素,如果第一个比第二个大,就交换它们两个;
  2. 对每一对相邻元素作同样的比价,从开始第一对到结尾的最后一对,这样在最后的元素就是最大的数;
  3. 针对所有的元素重复以上的步骤,除了数组最后已经排好序的数组;
  4. 重复步骤1~3,直到排序完成。

在这里插入图片描述

代码实现:

/**
 * 冒泡排序 —— 稳定
 */
public class BubbleSort {
    public static void main(String[] args) {
        int[] arr = {10, 8, 5, 13, 1, 6, 9};
        bubbleSort(arr);
    }

    private static void bubbleSort(int[] arr) {
        int len = arr.length;
        //外循环:内循环一次只会将一个大数冒泡到最前面,数组长度是多少就要冒泡多少次,即循环多少次
        for (int i = 0; i < len - 1; i++) {
            //内循坏:每次都比较相邻两个数的大小,然后交换位置,这里是将大的数往后放,会把一个最大的数往后冒泡
            for (int j = 0; j < len - i - 1; j++) {
                if (arr[j] > arr[j + 1]) {
                    int tmp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = tmp;
                }
            }
            System.out.println(Arrays.toString(arr));
        }
    }
}

选择排序(Selection Sort)

算法步骤 :

  1. 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置;
  2. 再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾;
  3. 重复第2步,直到所有元素均排序完毕。

在这里插入图片描述

代码实现:

/**
 * 选择排序 —— 不稳定
 */
public class SelectionSort {
    public static void main(String[] args) {
        int[] arr = {10, 8, 5, 13, 1, 6, 9};
        selectionSort(arr);
    }

    private static void selectionSort(int[] arr) {
        int len = arr.length;
        for (int i = 0; i < len - 1; i++) {
            //默认将当前下标作为最小值
            int minVal = i;
            //未排序的数组,将下标minVal与其中的每个元素都比较,选取实际最小的值,重新设置下标minVal
            for (int j = i + 1; j < len; j++) {
                if (arr[minVal] > arr[j]) {
                    minVal = j;
                }
            }
            //如果找出来的下标与当前迭代的下标不一致,则需要交换值,从小到大排序
            if (minVal != i) {
                int tmp = arr[i];
                arr[i] = arr[minVal];
                arr[minVal] = tmp;
            }
            System.out.println(Arrays.toString(arr));
        }
    }
}

插入排序(Insertion Sort)

算法步骤:

  1. 首先从第一个元素开始,该元素被认为是有序的;
  2. 取出下一个元素,在已经排序的元素序列中从后往前进行扫描;
  3. 如果该已排好序的元素大于新元素,则将该元素移到下一位置;
  4. 重复步骤3一直往前进行扫描比较,直到找到已排序的元素小于或者等于新元素的位置;
  5. 将新元素插入到该位置后;
  6. 重复步骤2~5。

在这里插入图片描述

代码实现:

/**
 * 插入排序 —— 稳定
 */
public class InsertionSort {
    public static void main(String[] args) {
        int[] arr = {10, 8, 5, 13, 1, 6, 9};
        insertionSort(arr);
    }

    private static void insertionSort(int[] arr) {
        //从第1个数开始
        for (int i = 1; i < arr.length; i++) {
            int val = arr[i], j = i;
            //当前选择的数与前面已排序的数组的每一个数进行比较,然后交换位置,这里是从小到大排序
            while (j > 0 && val < arr[j - 1]) {
                arr[j] = arr[j - 1];
                j--;
            }
            arr[j] = val;
        }
        System.out.println(Arrays.toString(arr));
    }
}

 

posted @ 2022-02-15 16:15  残城碎梦  阅读(267)  评论(0编辑  收藏  举报