十大排序算法之Java实现

1、冒泡排序

基本介绍:
冒泡排序(Bubble Sorting)的基本思想是:通过对待排序序列从前向后(从下标小的元素开始),依次比较相邻元素的值,若发现逆序则交换,使值较大的元素逐渐从前移向后部,就像水底下的气泡一样逐渐向上冒。

代码实现:

/**
     * 冒泡排序
     * @param arr 待排序的数组
     */
    public static void bubbleSort(int[] arr){
        int len;
        if (arr == null || (len = arr.length) < 2) return;
        // 总共进行len-1趟
        for (int i = 0; i < len - 1; i++) {
            // 每趟都从下标小的开始,每完成一趟长度减一
            for (int j = 1; j < len - i; j++) {
                // 发现逆序,则交换
                if (arr[j - 1] > arr[j]) {
                    swap(arr,j-1, j);
                }
            }
        }
    }

2、选择排序

基本介绍:
设一待排序的序列存于数组arr[n],第一次从a[0]~~a[n-1]中选取最大(小)的那个数然后与a[n-1](a[0])交换,第二次从a[0](a[1])~~a[n-2](a[n-1])中选取最大(小)的那个数与a[n-2](a[1])交换…第n-1次从a[0](a[n-2])~~a[1](a[n-1])中选取最大(小)的那个数与a[1](a[n-2])交换,共n-1次,得到一个有序序列。

代码实现:

/**
     * 选择排序
     * @param arr 待排序的数组
     */
    public static void selectSort(int[] arr){
        int len;
        if (arr == null || (len = arr.length) < 2) return;
        for (int i = len - 1; i > 0; i--) {
            int max = arr[i],max_index = i;
            // 找出最大值并记录下标
            for (int j = 0; j < i; j++) {
                if (arr[j] > max) {
                    max = arr[j];
                    max_index = j;
                }
            }
            swap(arr,max_index,i);
        }
    }

3、插入排序

基本介绍:
将n个待排序的元素看成是一个有序表和一个无序表,初始时,有序表只有一个元素(可认为是a[0]),无序表有n-1个元素,然后就是将无序表中的元素依次取出放入有序表的合适位置,最终使得有序表有n个元素即前面所说的n个待排序的元素。

代码实现:

/**
     * 插入排序
     * @param arr 待排序的数组
     */
    public static void insertSort(int[] arr){
        int len;
        if (arr == null || (len = arr.length) < 2) return;
        /*for (int i = 1; i < len; i++) {
            // 找插入的位置
            int index = i;
            while (index >0 && arr[index] < arr[index-1]) {
                swap(arr,index,index - 1);
                index--;
            }
        }*/

        // 优化
        for (int i = 1; i < len; i++) {
            int index = i,value = arr[i];
            while (index > 0 && value < arr[index-1]) {
                arr[index] = arr[index - 1];
                index--;
            }
            arr[index] = value;
        }
    }

4、希尔排序

基本介绍:
希尔排序是对插入排序的一种改进算法,也是一种插入排序,是希尔(Donald Shell)1959年提出的一种算法。将数组按一定增量分组,每一组使用插入排序进行排序,然后增量逐渐缩小,当缩小为1时,整个数组分为一组(这时的数组大部分元素已然有序),再进行插入排序。

代码实现:

/**
     * 希尔排序
     * @param arr 待排序的数组
     */
    public static void shellSort(int[] arr){
        int len;
        if (arr == null || (len = arr.length) < 2) return;
        // 定义步长
        int gap = len / 2;
        while (gap > 0) {
            // 分为gap个组,对每一组都进行插入排序
            for (int i = 0; i < gap; i++) {
                for (int j = i+gap; j < len; j+=gap) {
                    int value = arr[j];
                    int index = j;
                    while (index >= gap && arr[index - gap] > value) {
                        arr[index] = arr[index - gap];
                        index-=gap;
                    }
                    arr[index] = value;
                }
            }
            gap /= 2;
        }
    }

5、快速排序

基本介绍:
选择数组中一个元素(通常选择第一位)作为中轴pivot,使得数组中所有小于pivot的元素在pivot的左边,所有大于pivot的元素在pivot的右边,然后以pivot为分界线,递归的对左右两边进行上述操作,最终使得数组升序。

代码实现:

/**
     * 快速排序
     * @param arr 待排序的数组
     * @param left
     * @param right
     */
    public static void quickSort(int[] arr, int left, int right){
        if (left < right) {
            // 方式一
            /*int base = arr[left],j = left;
            // 选取最左边的为基准,使得数组中左边的都小于等于基准,右边的都大等于于基准
            for (int i = left + 1; i <= right; i++) {
                if (arr[i] < base) {
                    j++;
                    swap(arr,i,j);
                }
            }
            swap(arr, left, j);
            quickSort(arr, left, j - 1);
            quickSort(arr, j + 1, right);*/

            // 方式二
            int base = arr[left];
            int i = left, j = right;
            while (i < j) {
                // 找到左边第一个比base大的数
                while (i < j && arr[i] <= base) i++;
                swap(arr,i,j);
                // 找到右边第一个比base小的数
                while (i < j && arr[j] >= base) j--;
                swap(arr, i, j);
            }
            arr[j] = base;
            quickSort(arr, left, j - 1);
            quickSort(arr, j + 1, right);
        }
    }

6、归并排序

基本介绍:
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

代码实现:

/**
     * 归并排序
     * @param arr 待排序的数组
     * @param left
     * @param right
     */
    public static void mergeSort(int[] arr, int left, int right){
        if (left == right) return;
        int mid = left + (right - left) / 2;
        mergeSort(arr, left, mid);
        mergeSort(arr, mid + 1, right);
        int[] temp = new int[arr.length];
        int i = left, j = mid+1, index = 0;
        while (i <= mid && j <= right) {
            if (arr[i] < arr[j]) {
                temp[index++] = arr[i++];
            }else {
                temp[index++] = arr[j++];
            }
        }
        while (i <= mid) temp[index++] = arr[i++];
        while (j <= right) temp[index++] = arr[j++];
        index = 0;
        for (int k = left; k <= right; k++) {
            arr[k] = temp[index++];
        }
    }

7、堆排序

基本介绍:
堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。算法步骤为:

  • 将待排序的数组调整(shift)为大顶堆(小顶堆)
  • 将堆顶元素与最后一个元素交换,缩小范围继续调整(shift)

代码实现:

/**
     * 堆排序
     * @param arr 待排序的数组
     */
    public static void heapSort(int[] arr){
        int n;
        if (arr == null || (n = arr.length) < 2) return;
        // 先将数组调成大顶堆 从最后一叶子节点的父节点开始 即n/2-1
        for (int i = n/2-1; i >= 0; i--) {
            shift(arr, i, n);
        }
        // 将堆顶的数与最后一个叶节点交换 再调整 最终数组升序
        for (int i = n - 1; i > 0; i--) {
            swap(arr, 0, i);
            shift(arr,0, i);
        }
    }

/**
     * 调整下标i~j之间的元素
     * @param arr 待排序的数组
     * @param i
     * @param j
     */
    private static void shift(int[] arr, int i, int j){
        // 设根节点为0 则节点为i的左子节点为2*i+1 右子节点为2*i+2
        //int value = arr[i];
        for (int left = 2*i+1; left < j; left = 2*i+1) {
            // 选择左右子节点较大的一个
            if (left+1 < j && arr[left] < arr[left+1]) {
                left++;
            }
            if (arr[left] > arr[i]) {
                swap(arr,i,left);
                i = left;
            }else {
                break;
            }
        }
    }

8、计数排序

基本介绍:
计数排序是一种牺牲空间换取时间的算法,使用数组的下标来定位元素,算法步骤为:

  • 找出原数组中的最大值max和最小值min,计算桶数组的容量为max-min+1
  • 遍历原数组中的元素,并记录于桶数组中
  • 遍历桶数组,重新恢复于原数组中

代码实现:

/**
     * 计数排序
     * @param arr 待排序的数组
     */
    public static void countSort(int[] arr){
        int len;
        if (arr == null || (len = arr.length) <2) return;
        int max = arr[0],min = arr[0];
        // 找出最大值和最小值
        for (int i = 1; i < len; i++) {
            max = Math.max(max, arr[i]);
            min = Math.min(min, arr[i]);
        }
        // 计算桶的个数
        int count = max - min + 1;
        int[] bucket = new int[count];
        for (int i = 0; i < len; i++) {
            bucket[arr[i]-min]++;
        }
        int index = 0;
        // 遍历桶取出数据
        for (int i = 0; i < count; i++) {
            while (bucket[i] > 0) {
                arr[index++] = i + min;
                bucket[i]--;
            }
        }
    }

9、桶排序

基本介绍:
桶排序 (Bucket sort)或所谓的箱排序,是一个排序算法,工作的原理是将数组分到有限数量的桶子里,每个桶子再个别排序。

代码实现:

/**
     * 桶排序
     * @param arr 待排序的数组
     */
    public static void bucketSort(int[] arr){
        int len;
        if (arr == null || (len = arr.length) < 2) return;
        // 找出最大值与最小值
        int max = arr[0],min = arr[0];
        for (int i = 1; i < len; i++) {
            max = Math.max(max, arr[i]);
            min = Math.min(min, arr[i]);
        }
        // 计算桶的个数 间隔为10
        int count = (max - min) / 10 +1;
        List<Integer>[] bucket = new List[count];
        for (int i = 0; i < len; i++) {
            int index = (arr[i] - min) / 10;
            if (bucket[index] == null) {
                bucket[index] = new ArrayList<>();
            }
            bucket[index].add(arr[i]);
        }
        // 对每个桶里的元素分别排序
        for (int i = 0; i < count; i++) {
            if (bucket[i] == null) {
                continue;
            }
            bucket[i].sort(null); // 默认升序
        }
        int index = 0;
        // 依次取出桶里的元素
        for (int i = 0; i < count; i++) {
            if (bucket[i] == null) {
                continue;
            }
            for (int num :
                    bucket[i]) {
                arr[index++] = num;
            }
        }
    }

10、基数排序

基本介绍:
将所有待比较数值统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行依次排序。这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列。

代码实现:

/**
     * 基数排序
     * @param arr 待排序的数组
     */
    public static void radixSort(int[] arr){
        int len;
        if (arr == null || (len = arr.length) < 2) return;
        // 找出数组里最大值
        int max = arr[0];
        for (int i = 1; i < len; i++) {
            max = Math.max(max, arr[i]);
        }
        // 最大位数 即比较趟数
        int n = String.valueOf(max).length(),index;
        int[][] bucket = new int[10][len];
        int[] indexOfBucket = new int[10];
        for (int i = 0,m = 1; i < n; i++,m *= 10) {
            for (int j = 0; j < len; j++) {
                index = arr[j] / m % 10;
                bucket[index][indexOfBucket[index]] = arr[j];
                indexOfBucket[index]++;
            }
            index = 0;
            for (int j = 0; j < 10; j++) {
                for (int k = 0; k < indexOfBucket[j]; k++) {
                    arr[index++] = bucket[j][k];
                }
                indexOfBucket[j] = 0;
            }
        }
    }

至此,十大排序算法介绍完毕,最后附上一张对各类算法的性能描述图:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

b17a

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值