Java版常见排序算法总结

冒泡排序

时间复杂度O(n^2)
空间复杂度O(1)
最好O(n)
最坏O(n^2)
稳定

public static void bubbleSort(int[] arr) {
        //控制排序要排几趟
        for (int i = 0; i < arr.length; i++) {
            // 设定一个标记,若为true,则表示此次循环没有进行交换,也就是待排序列已经有序,排序已经完成。
            boolean flag = true;
            //控制要排序的书的个数
            for (int j = 0; j < arr.length - i - 1; j++) {
                if (arr[j] > arr[j + 1]) {
                    int tmp = arr[j + 1];
                    arr[j + 1] = arr[j];
                    arr[j] = tmp;

                    flag = false;
                }
            }
            if (flag) {
                break;
            }
        }
    }

选择排序

时间复杂度O(n^2)
空间复杂度O(1)
最好O(n^2)
最坏O(n^2)
不稳定

public static void selectSort(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            int min = i;
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[min] > arr[j]) {
                    min = j; // 记录目前能找到的最小值元素的下标

                }
            }
            // 将找到的最小值和i位置所在的值进行交换
            if (i != min) {
                int tmp = arr[i];
                arr[i] = arr[min];
                arr[min] = tmp;
            }
        }
    }

插入排序

时间复杂度O(n^2)
空间复杂度O(1)
最好O(n)
最坏O(n^2)
稳定

public static void insertSort(int[] arr) {
        //从下标为1的元素开始
        for (int i = 1; i < arr.length; i++) {
            //记录要插入的数据
            int tmp = arr[i];
            // 从已经排序的序列最右边的开始比较,找到比其小的数
            int j = i;
            while (j > 0 && tmp < arr[j - 1]) {
                arr[j] = arr[j - 1];//j-1位置上的数放到j上面,往后搬数据
                j--;
            }

            // 存在比其小的数,插入
            if (j != i) {
                arr[j] = tmp;
            }

        }
    }

快速排序

时间复杂度O(nlgn)
空间复杂度O(lgn)
最好O(nlgn)
最坏O(n^2)
不稳定

public static void quickSort(int[] arr, int left, int right) {
        if (left == right) {
            //只有一个数,有序
            return;
        }
        if (left > right) {
            //没有数,不需要排序
            return;
        }
        int div = Partition(arr, left, right);//找到基准值所在的下标
        quickSort(arr, left, div - 1);//递归排序基准值的左边
        quickSort(arr, div + 1, right);//递归排序基准值的右边

    }

    //此方法的目的是找到基准值所在的下标
    private static int Partition(int[] arr, int left, int right) {
        int begin = left;    // 不是 0
        int end = right;    // 不是 right - 1
        int pivot = arr[right];        // pivot 存的就是基准值

        while (begin < end) {
            // 如果基准值在最右边,想先动 begin
            // array[begin] 要 <= 不能 <
            while (begin < end && arr[begin] <= pivot) {
                begin++;
            }
            arr[end] = arr[begin];

            while (begin < end && arr[end] >= pivot) {
                end--;
            }
            arr[begin] = arr[end];
        }
        arr[begin] = pivot;
        return begin;
    }

堆排序

时间复杂度O(nlgn)
空间复杂度O(1)
最好O(nlgn)
最坏O(nlgn)
不稳定

public static void heapSort(int[] arr) {
        //建堆
        createHeap(arr);
        //减治处理
        for (int i = 0; i < arr.length; i++) {
            //最大的数是[0],最大的数应该放到下标是[length-1-i]
            Swap(arr, 0, arr.length - 1 - i);
            heapify(arr, arr.length - 1 - i, 0);
        }

    }


    private static void createHeap(int[] arr) {
        for (int i = (arr.length - 2) / 2; i >= 0; i--) {
            heapify(arr, arr.length, i);
        }
    }

    //向下调整
    private static void heapify(int[] arr, int size, int index) {
        while (2 * index + 1 < size) {
            int max = 2 * index + 1;
            if (max + 1 < size && arr[max + 1] > arr[max]) {
                max = 2 * index + 2;
            }
            if (arr[index] < arr[max]) {
                Swap(arr, index, max);
                index = max;
            } else {
                break;
            }
        }
    }

    private static void Swap(int[] arr, int index, int max) {
        int tmp = arr[index];
        arr[index] = arr[max];
        arr[max] = tmp;
    }

希尔排序

时间复杂度O(nlgn)
空间复杂度O(1)
最好O(nlg^2 n)
最坏O(nlg^2 n)
不稳定

 public static void ShellSort(int[] arr) {
        int gap = arr.length;
        while (true) {
            //gap = gap / 2;
            gap = gap / 3 + 1;
            shellSortWithGap(arr, gap);
            if (gap == 1) {
                break;
            }
        }
    }

    private static void shellSortWithGap(int[] arr, int gap) {
        //gap > 1 预排序
        //gap == 1 插排
        for (int i = 0; i < arr.length; i++) {
            int key = arr[i];
            int j = i - gap; //用来卡每个分组的边界值,方便分组内的数进行交换
            for (; j >= 0 && key < arr[j]; j = j - gap) {
                arr[j + gap] = arr[j];//分组边界值交换
            }
            arr[j + gap] = key;
        }
    }

归并排序

时间复杂度O(nlgn)
空间复杂度O(ln)
最好O(nlgn)
最坏O(nlgn)
稳定
外部排序

public static int[] mergeSort(int[] arr) {
        if (arr.length < 2) {
            return arr;
        }
        int middle = (int) Math.floor(arr.length / 2);
        int[] left = Arrays.copyOfRange(arr, 0, middle);
        int[] right = Arrays.copyOfRange(arr, middle, arr.length);
        return merge(mergeSort(left), mergeSort(right));
    }

    //合并两个区间为一个区间
    protected static int[] merge(int[] left, int[] right) {
        int[] result = new int[left.length + right.length];
        int i = 0;
        while (left.length > 0 && right.length > 0) {
            if (left[0] <= right[0]) {
                result[i++] = left[0];
                left = Arrays.copyOfRange(left, 1, left.length);
            } else {
                result[i++] = right[0];
                right = Arrays.copyOfRange(right, 1, right.length);
            }
        }

        while (left.length > 0) {
            result[i++] = left[0];
            left = Arrays.copyOfRange(left, 1, left.length);
        }
        while (right.length > 0) {
            result[i++] = right[0];
            right = Arrays.copyOfRange(right, 1, right.length);
        }
        return result;
    }

参考自公众号“五分钟学算法”。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值