java经典排序算法思想和源码解析

记录一下Java经典的排序算法,需要时不时来看一下

1. 插入排序

思想
将数组分成无序和有序两个部分,通常左边为有序区,然后从左到右遍历数组,将元素逐个插入到左边有序区中。
重点第一个元素我们将它看为是有序的,所以需要从第二个元素开始进行排序。

源码

// 插入排序
    static int[] insertSort(int[] arr) {

        // 默认第一个元素有序,从第二个开始循环
        for (int i = 1; i < arr.length; i++) {
            int key = arr[i];// 基准元素
            for (int j = i; j > 0 && arr[j - 1] > key; j--) {
                // 遇到比基准元素大的就交换
                arr[j] = arr[j - 1];
                arr[j - 1] = key;
            }
            System.out.println("本趟排序结果:" + Arrays.toString(arr));
        }
        return arr;
    }

结果

在这里插入图片描述
如果要换乘从大到小排,就把跟哨兵的比较换成 < 即可

优化

可以先进行比较,最后把元素插入到合适的位置

static void insertSort(int [] arr){
    for (int i = 1; i < arr.length; i++) {
        int j = i;
        int tmp = arr[i];
        while (j > 0 && arr[j - 1] > tmp) {
            arr[j] = arr[j - 1];
            j--;
        }
        arr[j] = tmp;
    }
}

2. 冒泡排序

思想
将数组分成有序和无序,通常我们将元素冒泡到数组右侧既右侧为有序,左侧为无序。
源码

// 冒泡排序
    int[] bubbleSort(int[] arr) {
        // 第一层交换 n-1 次
        for (int i = 0; i < arr.length - 1; i++) {
            // 第二重需要减去已排好的元素
            for (int j = 0; j < arr.length - 1 - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    swap(arr, j, j + 1);
                }
            }
            System.out.println("本趟排序结果:" + Arrays.toString(arr));
        }
        return arr;
    }
    void swap(int[] arr, int x, int y) {
        int temp = arr[x];
        arr[x] = arr[y];
        arr[y] = temp;
    }

如果从大到小排序,则值的比较换成<即可
结果
在这里插入图片描述

3. 快速排序

思想
主要是递归和分治,将序列选定第一个元素作为基准元素,然后分别两侧开始往中间移动:当右侧遇到比基准元素小的就停止移动,并把数据赋值给左侧。同理左侧遇到比基准元素大的就停止移动,并把数据赋值给右侧;当左右下标相遇的时候,这个时候就把基准元素赋值给这个下标,这时左侧的都比基准小,右侧的都比基准大,一趟排序就完成了;
之后使用分治思想,分别递归基准左边的元素,以及基准右边的元素,最后整个序列就会变成有序的。
源码

// 快速排序
    Integer[] quickSort(Integer[] arr, int left, int right) {

        if (arr.length == 0) {
            return null;
        }
        if (left < right) {
            // 选择第一个元素为基准元素
            int key = arr[left];
            int l = left;
            int r = right;
            while (l < r) {
                // 先移动右边的下标
                while (l < r && arr[r] >= key) {
                    r--;
                }
                // 如果找到比基准数据小的,停止while循环,并把他的值赋值给最左侧
                arr[l] = arr[r];
                // 再移动左边的下标
                while (l < r && arr[l] <= key) {
                    l++;
                }
                // 如果找到比基准数据大的,停止循环,并把他的值赋值给最右侧
                arr[r] = arr[l];
            }
            // 当 l=r 的时候,说明这一趟循环结束,这时左边的元素都比他小,右边的元素都比他大,l就是中间位置的下标
            arr[l] = key;
            quickSort(arr, left, l - 1);
            quickSort(arr, l + 1, right);
        }
        return arr;
    }

结果
在这里插入图片描述

4. 归并排序

思想
归并字面意思就可以理解为合并,将数组不断的进行左右拆分,直到拆分成一个元素时再对数组进行排序合并,然后不断的合并两个有序的数组,最终整个数组就是有序的。
源码

// 归并排序
    int[] mergeSort(int[] arr) {

        if (null == arr || arr.length < 2) {
            return arr;
        }
        int center = arr.length >> 1;
        int[] leftArr = Arrays.copyOfRange(arr, 0, center);
        int[] rightArr = Arrays.copyOfRange(arr, center, arr.length);
        System.out.println("拆分数组结果: " + Arrays.toString(leftArr) + " <---> " + Arrays.toString(rightArr));
        // 递归拆分数组并合并
        return merge(mergeSort(leftArr), mergeSort(rightArr));
    }

    // 归并排序,合并两个数组
    private int[] merge(int[] arrLeft, int[] arrRight) {
        int i = 0, j = 0, k = 0;
        // 存放合并后的数组
        int[] newArr = new int[arrLeft.length + arrRight.length];
        // 两个数组都从第一个元素开始进行比较,将小的放入
        while (i < arrLeft.length && j < arrRight.length) {
            if (arrLeft[i] <= arrRight[j]) {
                newArr[k++] = arrLeft[i++];
            } else {
                newArr[k++] = arrRight[j++];
            }
        }
        // 如果左侧数组有剩余,证明他比新数组中的元素都大,那么把它的元素全部追加在新数组中
        while (i < arrLeft.length) {
            newArr[k++] = arrLeft[i++];
        }
        // 同样如果右侧数组有剩余,证明他比新数组中的元素都大,那么把它的元素全部追加在新数组中
        while (j < arrRight.length) {     //序列2中多余的元素移入新数组
            newArr[k++] = arrRight[j++];
        }
        System.out.println("合并结果: " + Arrays.toString(newArr));
        return newArr;
    }

结果
在这里插入图片描述

5. 选择排序

思想
将数组分为有序去和无序区,每次从无序区中找到最小的元素然后和无序区第一个元素交换;然后将有序区扩大一位,直到全部变成有序的。
源码

// 选择排序
    int[] selectSort(int[] arr) {

        if (null == arr) {
            return null;
        }
        for (int i = 0; i < arr.length - 1; i++) {
            // 假设无序区第一个元素是最小的
            int min = i;
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[j] < arr[min]) {
                    min = j;
                }
            }
            swap(arr, i, min);
            System.out.println("本趟排序结果:" + Arrays.toString(arr));
        }
        return arr;
    }
    void swap(int[] arr, int x, int y) {
        int temp = arr[x];
        arr[x] = arr[y];
        arr[y] = temp;
    }

结果

在这里插入图片描述

6. 希尔排序

思想
希尔排序其实就是插入排序的变种。思想就是每次取一个增量步长,针对此步长间隔开的子序列进行插入排序,然后逐渐缩短这个步长的值,直到最后步长为一,树列就变成有序数列。
重点一般初次的步长为数组的二分之一,之后每次再减半,直到增量为1。

源码

// 希尔排序
    int[] hillSort(int[] arr){

        int j;
        int tmp;
        // 步长每次除以2
        for (int gap = arr.length / 2; gap >0; gap /= 2) {
            for (int i = gap; i < arr.length;i++) {
                tmp = arr[i];
                // 对在这个步长上的数组进行插入排序
                for (j = i; j >= gap && tmp< arr[j - gap]; j -= gap) {
                    arr[j] = arr[j - gap];
                }
                arr[j] = tmp;
                System.out.println("本趟排序结果:" + Arrays.toString(arr));
            }
        }
        return arr;
    }

结果
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值