Bootstrap

三傻排序的比较(选择,冒泡,插入)

在学习排序算法时,选择排序、冒泡排序和插入排序是最常见的基础排序算法。但是,尽管这些算法看起来非常相似,它们在实际应用中的效率和性能却有所不同。本文将详细比较这三种排序算法的时间复杂度、空间复杂度。

比较总结

排序算法时间复杂度(最坏/平均/最好)空间复杂度稳定性总结
选择排序O(n^2) / O(n^2) / O(n^2)O(1)不稳定选择排序就像每次去找最小的苹果,把它拿过来放到最前面。比较次数多,但并不保证相同值的苹果顺序不变。
冒泡排序O(n^2) / O(n^2) / O(n)O(1)稳定冒泡排序就像水中泡泡,每次拿两个相邻的元素交换位置,把最大的“泡泡”挤到最后面。对已经排序的部分有点帮助。
插入排序O(n^2) / O(n^2) / O(n)O(1)稳定插入排序像扑克牌,每次从剩下的牌中选一张,插入到已经排好序的部分。只要原本部分已经排得差不多,插入排序就很快。
解释:
  • 选择排序:就像在一堆乱七八糟的苹果里,每次都找最小的一个放到最前面,直到找完所有苹果。这样做效率低,因为每次都要扫描整个数组。并且,交换位置时会改变相同数值元素的顺序,所以它是不稳定的。

  • 冒泡排序:它的工作方式像水中的气泡,每次把最小(或者最大)的一泡气泡“冒泡”到水面。这样做最差的情况就像是给每个气泡都挤出来一次,效率比较差。不过,如果数据本来就已经有点有序了,冒泡排序会比选择排序好,因为它可以提前结束。冒泡排序是稳定的,也就是说,相同的数值会保持原来的顺序。

  • 插入排序:插入排序就像你在玩扑克牌,已经排好的一部分牌,就像一个顺序的队列,后面的牌从后面插进这个顺序队列。如果已经排得差不多了,那么插入排序就能非常快速地完成任务,效率提升很多。它也是稳定的,意思是相同的数字不会改变顺序。

总结:
  • 选择排序:非常简单,但因为每次都要比较整个数组,所以它的效率较差,尤其是大数据时。它是不稳定的,不适合用在需要保留相等元素顺序的场景。
  • 冒泡排序:虽然每次“冒泡”都能把大的数挤到最后,但它效率也不高,尤其是需要进行多轮比较时。它是稳定的,如果数据部分有序,它比选择排序要好一些。
  • 插入排序:适合数据已经有序或者部分有序的情况,可以非常高效。它也是稳定的,是一个非常实用的排序算法,尤其是数据量不大时。

分别分析:

1. 选择排序(Selection Sort)

选择排序是一种简单的排序算法,它的基本思想是:

  • 每次从待排序的数组中选择最小的元素,然后将其与未排序部分的第一个元素交换。
  • 重复这个过程,直到所有元素都被排序。
选择排序的工作原理:
  1. 找到数组中最小的元素。
  2. 将其与数组的第一个元素交换。
  3. 然后对剩下的元素继续执行相同操作,直到整个数组有序。

选择排序的Java代码实现:

public class SelectionSort {
    public static void selectionSort(int[] arr) {
        int n = arr.length;
        
        // 遍历数组
        for (int i = 0; i < n - 1; i++) {
            // 假设当前元素是最小的
            int minIndex = i;
            
            // 查找剩余部分的最小元素
            for (int j = i + 1; j < n; j++) {
                if (arr[j] < arr[minIndex]) {
                    minIndex = j;
                }
            }
            
            // 交换最小元素与当前位置的元素
            int temp = arr[i];
            arr[i] = arr[minIndex];
            arr[minIndex] = temp;
        }
    }

    public static void printArray(int[] arr) {
        for (int num : arr) {
            System.out.print(num + " ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        int[] arr = {64, 25, 12, 22, 11};
        System.out.println("Original Array:");
        printArray(arr);

        selectionSort(arr);

        System.out.println("Sorted Array:");
        printArray(arr);
    }
}
选择排序的时间和空间复杂度:
  • 时间复杂度:O(n^2),在每次选择最小值时需要遍历剩余部分,因此时间复杂度为 O(n^2)。
  • 空间复杂度:O(1),选择排序是原地排序算法,仅使用常数级别的额外空间。

2. 冒泡排序(Bubble Sort)

冒泡排序的基本思想是:

  • 通过多次比较相邻的元素,若顺序错误则交换它们。
  • 每一轮遍历将当前未排序部分中的最大元素“冒泡”到数组的末尾。
  • 重复这个过程,直到整个数组有序。
冒泡排序的工作原理:
  1. 从数组的第一个元素开始,比较相邻的两个元素,如果顺序错误就交换它们。
  2. 每一轮遍历后,最大的元素被交换到末尾。
  3. 重复遍历,直到所有元素都已排序。

冒泡排序的Java代码实现:

public class BubbleSort {
    public static void bubbleSort(int[] arr) {
        int n = arr.length;
        
        // 外层循环,控制比较的轮数
        for (int i = 0; i < n - 1; i++) {
            // 内层循环,进行相邻元素的比较和交换
            for (int j = 0; j < n - 1 - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    // 交换相邻元素
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }

    public static void printArray(int[] arr) {
        for (int num : arr) {
            System.out.print(num + " ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        int[] arr = {64, 25, 12, 22, 11};
        System.out.println("Original Array:");
        printArray(arr);

        bubbleSort(arr);

        System.out.println("Sorted Array:");
        printArray(arr);
    }
}
冒泡排序的时间和空间复杂度:
  • 时间复杂度:O(n^2),在最坏和最常见的情况下,需要两层嵌套循环,因此时间复杂度是 O(n^2)。
  • 空间复杂度:O(1),冒泡排序是原地排序算法,不需要额外的存储空间。

3. 插入排序(Insertion Sort)

插入排序的基本思想是:

  • 从第二个元素开始,将每个元素插入到已经排好序的部分中。
  • 每次插入时,先与已经排序的元素进行比较,找到合适的位置插入。
插入排序的工作原理:
  1. 从数组的第二个元素开始,将其插入到前面已排序部分的合适位置。
  2. 每次插入时,从右向左移动元素,直到找到合适的位置。
  3. 重复这一过程,直到整个数组有序。
插入排序的Java代码实现:
public class InsertionSort {
    public static void insertionSort(int[] arr) {
        int n = arr.length;
        
        // 从第二个元素开始插入
        for (int i = 1; i < n; i++) {
            int key = arr[i];
            int j = i - 1;
            
            // 移动比key大的元素
            while (j >= 0 && arr[j] > key) {
                arr[j + 1] = arr[j];
                j = j - 1;
            }
            
            // 插入key元素
            arr[j + 1] = key;
        }
    }

    public static void printArray(int[] arr) {
        for (int num : arr) {
            System.out.print(num + " ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        int[] arr = {64, 25, 12, 22, 11};
        System.out.println("Original Array:");
        printArray(arr);

        insertionSort(arr);

        System.out.println("Sorted Array:");
        printArray(arr);
    }
}
插入排序的时间和空间复杂度:
  • 时间复杂度:O(n^2),在最坏情况下(当数组是倒序时),需要两层循环,因此时间复杂度为 O(n^2)。但在部分有序的数组中,插入排序的表现比选择排序和冒泡排序更优。
  • 空间复杂度:O(1),插入排序是原地排序算法,只需要常数级别的额外空间。
;