排序算法笔记

冒泡算法

1,冒泡算法是原地排序算法吗?

冒泡的过程只涉及相邻数据的交换操作,只需要常量级的临时空间,所以他的空间复杂度为O(1),是一个原地排序算法.

2,冒泡算法是稳定的排序算法吗?

为了保证冒泡算法的稳定系,当有相邻两个元素大小相等的时候,我们不做交换,所以冒泡算法是稳定的排序算法.

3,冒泡排序的时间复杂度是多少?

最好的情况,要排序的数据已经有序了,我们只进行一次冒泡操作,所以时间复杂度是O(n),最坏的情况是要排序的数据是倒序的,我们要进行n次冒泡操作,所以时间复杂度是O(n^2)

代码优化

在数据完全有序的时候展现出最优时间复杂度,为O(n)。其他情况下,几乎总是O( n^2 )。因此,算法在数据基本有序的情况下,性能最好。

要使算法在最佳情况下有O(n)复杂度,需要做一些改进,增加一个swap的标志,当前一轮没有进行交换时,说明数组已经有序,没有必要再进行下一轮的循环了,直接退出。

public class OptimizedBubbleSort {

    public static void optimizedBubbleSort(int[] arr) {
        boolean swapped;
        int n = arr.length;

        for (int i = 0; i < n - 1; i++) {
            swapped = false;

            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;
                    swapped = true;
                }
            }

            // 如果在一次遍历中没有发生交换,说明数组已经有序,可以提前结束排序
            if (!swapped) {
                break;
            }
        }
    }

    public static void main(String[] args) {
        int[] arr = {3, 8, 2, 5, 1, 4, 7, 6};
        optimizedBubbleSort(arr);

        for (int num : arr) {
            System.out.print(num + " ");
        }
    }
}

插入排序

算法描述

把待排序的数组分成已排序和未排序两部分,初始的时候把第一个元素认为是已排好序的。

从第二个元素开始,在已排好序的子数组中寻找到该元素合适的位置并插入该位置。

重复上述过程直到最后一个元素被插入有序子数组中。

IMG20230427-102454745.png
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;

            // 将arr[i]插入到已排序的子数组arr[0...i-1]中
            while (j >= 0 && arr[j] > key) {
                arr[j + 1] = arr[j];
                j--;
            }
            arr[j + 1] = key;
        }
    }

    public static void main(String[] args) {
        int[] arr = {3, 8, 2, 5, 1, 4, 7, 6};
        insertionSort(arr);

        for (int num : arr) {
            System.out.print(num + " ");
        }
    }
}

选择排序

算法描述

在未排序序列中找到最小(大)元素,存放到排序序列的起始位置

从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。

重复第二步,直到所有元素均排序完毕。

归并排序

快速排序

算法描述

从数列中挑出一个元素,称为"基准"(pivot),

重新排序数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面(相同的数可以到任何一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。

递归地(recursively)把小于基准值元素的子数列和大于基准值元素的子数列排序。

16311248-90700b1c67c6abf9.png
public class QuickSort {
    public static void quickSort(int[] arr, int low, int high) {
        if (low < high) {
            int pivotIndex = partition(arr, low, high);
            quickSort(arr, low, pivotIndex - 1);
            quickSort(arr, pivotIndex + 1, high);
        }
    }

    private static int partition(int[] arr, int low, int high) {
        int pivot = arr[low];
        int i = low;
        int j = high;

        while (i < j) {
            while (i < j && arr[j] >= pivot) {
                j--;
            }
            if (i < j) {
                arr[i] = arr[j];
                arr[j]=pivot;
                i++;
            }

            while (i < j && arr[i] <= pivot) {
                i++;
            }
            if (i < j) {
                arr[j] = arr[i];
                arr[i]=pivot;
                j--;
            }
        }
        return i;
    }

    public static void main(String[] args) {
        int[] arr = {1, 8, 2, 5, 3, 4, 7, 6, 0, 9};
        quickSort(arr, 0, arr.length - 1);

        for (int num : arr) {
            System.out.print(num + " ");
        }
    }
}

你可能感兴趣的:(排序算法笔记)