• 六大排序算法:插入、选择、冒泡、快排、希尔、归并


    1、插入排序

    解析:第一个元素设定为已经排好序,依次选择后续的元素插入到已经排好序的组内进行排序。

    图示:

    代码:

    1. public static void insertionSort(int[] arr) {
    2. int n = arr.length;
    3. for (int i = 1; i < n; i++) {
    4. int key = arr[i];
    5. int j = i - 1;
    6. // 将比当前元素大的元素向右移动
    7. while (j >= 0 && arr[j] > key) {
    8. arr[j + 1] = arr[j];
    9. j--;
    10. }
    11. // 插入当前元素到正确的位置
    12. arr[j + 1] = key;
    13. }
    14. }

    时间复杂度:最坏情况下为O(N^2),此时待排序列为逆序,或者说接近逆序
          最好情况下为O(N),此时待排序列为升序,或者说接近升序。
    空间复杂度:O(1)

    2、选择(比较)排序:

    解析:每次从待排序列中选出一个最小值,然后放在序列的起始位置,直到全部待排数据排完。

    图示:

    代码:

    1. public static void selectionSort(int[] arr) {
    2. int n = arr.length;
    3. for (int i = 0; i < n - 1; i++) {
    4. int minIndex = i;
    5. // 寻找未排序部分的最小元素的索引
    6. for (int j = i + 1; j < n; j++) {
    7. if (arr[j] < arr[minIndex]) {
    8. minIndex = j;
    9. }
    10. }
    11. // 将找到的最小元素与未排序部分的第一个元素交换
    12. int temp = arr[i];
    13. arr[i] = arr[minIndex];
    14. arr[minIndex] = temp;
    15. }
    16. }

    时间复杂度:最坏情况:O(N^2)
          最好情况:O(N^2)
    空间复杂度:O(1)

    3、冒泡排序

    解析:左边大于右边交换,一趟排下来最大的在右边

    图示:

    代码:

    1. public static void bubbleSort(int[] arr) {
    2. int n = arr.length;
    3. for (int i = 0; i < n - 1; i++) {
    4. for (int j = 0; j < n - i - 1; j++) {
    5. if (arr[j] > arr[j + 1]) {
    6. // 交换arr[j]和arr[j + 1]
    7. int temp = arr[j];
    8. arr[j] = arr[j + 1];
    9. arr[j + 1] = temp;
    10. }
    11. }
    12. }
    13. }

    时间复杂度:最坏情况:O(N^2)
          最好情况:O(N)
    空间复杂度:O(1)

    4、快排

    解析:

    • 1.先从数列中取出一个数作为基准数。
    • 2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。
    • 3.再对左右区间重复第二步,直到各区间只有一个数或者这个区间不存在。

    图示:

    代码:

    1. public static void quickSort(int[] arr, int low, int high) {
    2. if (low < high) {
    3. // 划分数组,返回分区点的索引
    4. int pivotIndex = partition(arr, low, high);
    5. // 递归排序分区左侧和右侧的子数组
    6. quickSort(arr, low, pivotIndex - 1);
    7. quickSort(arr, pivotIndex + 1, high);
    8. }
    9. }
    10. public static int partition(int[] arr, int low, int high) {
    11. int pivot = arr[high]; // 选择最后一个元素作为基准元素
    12. int i = low - 1;
    13. for (int j = low; j < high; j++) {
    14. if (arr[j] < pivot) {
    15. i++;
    16. // 交换arr[i]和arr[j]
    17. int temp = arr[i];
    18. arr[i] = arr[j];
    19. arr[j] = temp;
    20. }
    21. }
    22. // 将基准元素放到正确的位置
    23. int temp = arr[i + 1];
    24. arr[i + 1] = arr[high];
    25. arr[high] = temp;
    26. return i + 1;
    27. }

    时间复杂度:O(NlogN)
    空间复杂度:O(1)

    5、希尔排序

    解析:

    1.先选定一个小于N的整数gap作为第一增量,然后将所有距离为gap的元素分在同一组,并对每一组的元素进行直接插入排序。然后再取一个比第一增量小的整数作为第二增量,重复上述操作…
    2.当增量的大小减到1时,就相当于整个序列被分到一组,进行一次直接插入排序,排序完成。

    图示:

    代码:

    1. public static void shellSort(int[] arr) {
    2. int n = arr.length;
    3. // 初始间隔设为数组长度的一半,然后逐渐缩小间隔
    4. for (int gap = n / 2; gap > 0; gap /= 2) {
    5. for (int i = gap; i < n; i++) {
    6. int temp = arr[i];
    7. int j;
    8. for (j = i; j >= gap && arr[j - gap] > temp; j -= gap) {
    9. arr[j] = arr[j - gap];
    10. }
    11. arr[j] = temp;
    12. }
    13. }
    14. }

    时间复杂度平均:O(N)
    空间复杂度:O(1)

    6、归并排序

    解析:

    1. 将待排序的线性表不断地切分成若干个子表,直到每个子表只包含一个元素,这时,可以认为只包含一个元素的子表是有序表。
    2. 将子表两两合并,每合并一次,就会产生一个新的且更长的有序表,重复这一步骤,直到最后只剩下一个子表,这个子表就是排好序的线性表

    图示:

    代码:

    1. public static void mergeSort(int[] arr) {
    2. int n = arr.length;
    3. if (n <= 1) {
    4. return; // 如果数组长度小于等于1,无需排序
    5. }
    6. // 将数组分成两个子数组
    7. int mid = n / 2;
    8. int[] left = new int[mid];
    9. int[] right = new int[n - mid];
    10. System.arraycopy(arr, 0, left, 0, mid);
    11. System.arraycopy(arr, mid, right, 0, n - mid);
    12. // 递归排序左右子数组
    13. mergeSort(left);
    14. mergeSort(right);
    15. // 合并两个有序子数组
    16. merge(arr, left, right);
    17. }
    18. public static void merge(int[] arr, int[] left, int[] right) {
    19. int n1 = left.length;
    20. int n2 = right.length;
    21. int i = 0, j = 0, k = 0;
    22. while (i < n1 && j < n2) {
    23. if (left[i] <= right[j]) {
    24. arr[k] = left[i];
    25. i++;
    26. } else {
    27. arr[k] = right[j];
    28. j++;
    29. }
    30. k++;
    31. }
    32. while (i < n1) {
    33. arr[k] = left[i];
    34. i++;
    35. k++;
    36. }
    37. while (j < n2) {
    38. arr[k] = right[j];
    39. j++;
    40. k++;
    41. }
    42. }

    时间复杂度平均:O(N)
    空间复杂度:O(N)

  • 相关阅读:
    算法刷题日志——回溯算法
    自定义ProjectSettings设置项
    JS笔记--Web APIS(下)
    Spring IOC工作流程
    选择和操作元素
    JavaScript期末大作业 基于HTML+CSS+JavaScript技术制作web前端开发个人博客(48页)
    利用软raid程序来配置实现“RAID1+0”阵列
    SpringBoot-7-对Web开发静态资源的处理
    纵横交织的功能的单元测试
    16位简单ASM题的记录——[HGAME 2022 week1]easyasm
  • 原文地址:https://blog.csdn.net/m0_47743353/article/details/134271407