java 排序算法之归并排序

目录
  • 简单介绍
  • 基本思想
  • 思路分析
  • 代码实现
    • 对代码的一些改进
  • 大数据量耗时测试
  • 复杂度

简单介绍

归并排序(merge sort)是利用 归并 的思想实现的排序方法,该算法采用经典的 分治(divide-and-conquer)策略

  • 分(divide):将问题分成一些小的问题,然后递归求解
  • 治(conquer):将分的阶段得到的各答案「修补」在一起

即:分而治之

该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

基本思想

  • 分:分的过程只是为了分解
  • 治:分组完成后,开始对每组进行排序,然后合并成一个有序序列,直到最后将所有分组合并成一个有序序列

可以看到这种结构很像一棵完全二叉树,本文的归并排序我们采用递归实现(也可采用迭代的方式实现)。分阶段可以理解为就是递归拆分子序列的过程。

:这些数从始至终都在一个数组里(只是抽象的想想成两个数组),除了排序时会把要排序的数copy到一个临时数组里面,这里如果不懂后面看了代码后,再返回来思考就懂了。一定要思考!!!!

下面的动图可以很直观的看到整个算法实现的过程,初体验一下吧,后面的代码可以结合上面的图,和这个动图,来整理一下逻辑

多个数排序动图:

思路分析

对于分阶段相对较简单,下面着重来对治阶段进行分析。

合并相邻有序子序列分析:下图以 归并排序的最后一次合并 为例来分析,即对应上图的 [4,5,7,8][1,2,3,6] 两个已经有序的子序列合并为最终序列 [1,2,3,4,5,6,7,8],下图展示了实现步骤

如图所示:这是最后一次的合并 操作,是两个有序序列合并为最终的有序序列。

  • 1.从有序序列开始挨个比较,这里比较 4 和 1,1 < 4,那么 1 进入临时数组 temp中,并且将自己的指针右移动一位
  • 2.由于图上绿色部分上一次 4 大于 1,指针并未移动,然后 4 和 2 对比,2 < 4 , 2 进入到临时数组中,并且将自己的指针右移动一位
  • 3. ...
  • 4.如果某一组已经全部进入了临时数组,那么剩余一组的剩余有序序列直接追加到临时数组中
  • 5.最后,将 temp 内容拷贝到原数组中去,完成排序

代码实现

先实现合并方法,这个是该算法中最重要的,你也看可以直接看后面的完整算法代码,再返回来思考,这个都随你。此次是因为 的步骤需要用到 的这个,所以我这里就先放 合并的代码了。

 /**
     *
     *  最难的是合并,所以可以先完成合并的方法,此方法请参考 基本思想 和 思路分析中的图解来完成
     *  动脑筋
     *
     *
     *
     * @param arr   要排序的原始数组
     * @param left  因为是合并,所以要得到左右两边的的数组信息,这个是左侧数组的第一个索引值
     * @param mid   因为是一个数组,标识是第一个数组的最后一个索引,即 mid+1 是右侧数组的第一个索引,即中间索引
     * @param right 右侧数组的结束索引,右边数组的最后一个数
     * @param temp  临时空间,临时数组
     */
    public void merge(int[] arr, int left, int mid, int right, int[] temp) {
        // 定时临时变量,用来遍历数组比较
        int l = left;  // 左边有序数组的初始索引
        int r = mid + 1; // 右边有序数组的初始索引
        int t = 0; // temp 数组中当前最后一个有效数据的索引

        // 1. 按思路先将两个数组(有序的)有序的合并到 temp 中
        // 因为是合并两个数组,所以需要两边的数组都还有值的时候才能进行 比较合并
        // 若其中一个数组的值遍历完了(取完了),那么就跳出该循环,把另一个数组所剩的值,直接copy进临时数组即可
        while (l <= mid && r <= right) {
            // 如果左边的比右边的小,则将左边的该元素填充到 temp 中
            // 并移动 t++,l++,好继续下一个
            if (arr[l] < arr[r]) {
                temp[t] = arr[l];
                t++;//移动 temp 临时数组中当前最后一个有效数据的索引
                l++; //左边原始数组的索引移动
            }
            // 否则则将右边的移动到 temp 中
            else {
                temp[t] = arr[r];
                t++;//移动 temp 临时数组中当前最后一个有效数据的索引
                r++;//右边原始数组的索引移动
            }
        }
        // 2. 如果有任意一边的数组还有值,则依序将剩余数据填充到 temp 中
        // 如果左侧还有值
        while (l <= mid) {
            temp[t] = arr[l];
            t++;
            l++;
        }
        // 如果右侧还有值
        while (r <= right) {
            temp[t] = arr[r];
            t++;
            r++;
        }

        // 3. 将 temp 数组,拷贝到原始数组
        // 注意:只拷贝当前temp有效数据到对应的原始数据中,通俗点说,就是原始数组中要排序的数据,通过temp排成了有序的,然后将temp中的有序数据将原始数组中原来要排序的那部分覆盖了就行了
        int tempL = left; // 从左边开始拷贝,左边第一个值的索引
        t = 0;  // temp 中的有效值索引,有效值边界可以通过 right 判定,因为合并两个数组到 temp 中,边界就是 right ,这里自己好好想想
        /*
         * 对于 8,4,5,7,1,3,6,2 这个数组,
         * 从栈顶开始合并:8,4 | 5,7       1,3 | 6,2
         * 先左递归的话:
         * 第一次:8,4 合并:tempL=0,right=1
         * 第二次:5,7 合并:tempL=2,right=3
         * 第三次:4,8 | 5,7 进行合并,tempL=0,right=3
         * 直到左递归完成,得到左侧一个有序的序列:4,5,7,8 然后再开始递归右边那个无序的
         * 最后回到栈底分解成两个数组的地方,将两个数组合并成一个有序数组
         * 这里真的得自己想了,我只能这么说了。
         */
        System.out.println("tempL=" + tempL + "; right=" + right);
        while (tempL <= right) {
            arr[tempL] = temp[t];
            tempL++;
            t++;
        }
    }

需要注意的是:这个图一定要看明白:

  • 1.一直分解,到栈顶首次合并时,是两个数字,也就是说,左侧数组只有一个数字,右侧数组只有一个数字
  • 2.左侧数组只有一个数字时,l = 0,r = 1,那么 mid = 0,边界判定时要用 l <= mid && r <= right ,否则就会跳过对比合并了

完整代码如下

    @Test
    public void sortTest() {
        int[] arr = new int[]{8, 4, 5, 7, 1, 3, 6, 2};
        int[] temp = new int[arr.length];
        mergeSort(arr, 0, arr.length - 1, temp);
        System.out.println("排序后:" + Arrays.toString(arr));
    }

    /**
     * 分 和 合并
     */
    public void mergeSort(int[] arr, int left, int right, int[] temp) {
        //确保两个数组中分别都存在至少一个数字
        if (left < right) {
            int mid = (left + right) / 2;
            // 先分解左侧
            mergeSort(arr, left, mid, temp);
            // 再分解右侧
            mergeSort(arr, mid + 1, right, temp);
            // 最后合并
            // 由于是递归,合并这里一定是栈顶的先执行(两边数组各只有一个数时)
            // 第一次:left = 0,right=1
            // 第二次:left = 2,right=3
            // 第三次:left = 0,right=3
//            System.out.println("left=" + left + ";right=" + right);
            merge(arr, left, mid, right, temp);
        }
    }

     /**
     *
     *  最难的是合并,所以可以先完成合并的方法,此方法请参考 基本思想 和 思路分析中的图解来完成
     *  动脑筋
     *
     *
     *
     * @param arr   要排序的原始数组
     * @param left  因为是合并,所以要得到左右两边的的数组信息,这个是左侧数组的第一个索引值
     * @param mid   因为是一个数组,标识是第一个数组的最后一个索引,即 mid+1 是右侧数组的第一个索引,即中间索引
     * @param right 右侧数组的结束索引,右边数组的最后一个数
     * @param temp  临时空间,临时数组
     */
    public void merge(int[] arr, int left, int mid, int right, int[] temp) {
        // 定时临时变量,用来遍历数组比较
        int l = left;  // 左边有序数组的初始索引
        int r = mid + 1; // 右边有序数组的初始索引
        int t = 0; // temp 数组中当前最后一个有效数据的索引

        // 1. 按思路先将两个数组(有序的)有序的合并到 temp 中
        // 因为是合并两个数组,所以需要两边的数组都还有值的时候才能进行 比较合并
        // 若其中一个数组的值遍历完了(取完了),那么就跳出该循环,把另一个数组所剩的值,直接copy进临时数组即可
        while (l <= mid && r <= right) {
            // 如果左边的比右边的小,则将左边的该元素填充到 temp 中
            // 并移动 t++,l++,好继续下一个
            if (arr[l] < arr[r]) {
                temp[t] = arr[l];
                t++;//移动 temp 临时数组中当前最后一个有效数据的索引
                l++; //左边原始数组的索引移动
            }
            // 否则则将右边的移动到 temp 中
            else {
                temp[t] = arr[r];
                t++;//移动 temp 临时数组中当前最后一个有效数据的索引
                r++;//右边原始数组的索引移动
            }
        }
        // 2. 如果有任意一边的数组还有值,则依序将剩余数据填充到 temp 中
        // 如果左侧还有值
        while (l <= mid) {
            temp[t] = arr[l];
            t++;
            l++;
        }
        // 如果右侧还有值
        while (r <= right) {
            temp[t] = arr[r];
            t++;
            r++;
        }

        // 3. 将 temp 数组,拷贝到原始数组
        // 注意:只拷贝当前temp有效数据到对应的原始数据中,通俗点说,就是原始数组中要排序的数据,通过temp排成了有序的,然后将temp中的有序数据将原始数组中原来要排序的那部分覆盖了就行了
        int tempL = left; // 从左边开始拷贝,左边第一个值的索引
        t = 0;  // temp 中的有效值索引,有效值边界可以通过 right 判定,因为合并两个数组到 temp 中,边界就是 right ,这里自己好好想想
        /*
         * 对于 8,4,5,7,1,3,6,2 这个数组,
         * 从栈顶开始合并:8,4 | 5,7       1,3 | 6,2
         * 先左递归的话:
         * 第一次:8,4 合并:tempL=0,right=1
         * 第二次:5,7 合并:tempL=2,right=3
         * 第三次:4,8 | 5,7 进行合并,tempL=0,right=3
         * 直到左递归完成,得到左侧一个有序的序列:4,5,7,8 然后再开始递归右边那个无序的
         * 最后回到栈底分解成两个数组的地方,将两个数组合并成一个有序数组
         * 这里真的得自己想了,我只能这么说了。
         */
        System.out.println("tempL=" + tempL + "; right=" + right);
        while (tempL <= right) {
            arr[tempL] = temp[t];
            tempL++;
            t++;
        }
    }

测试输出

tempL=0; right=1
tempL=2; right=3
tempL=0; right=3
tempL=4; right=5
tempL=6; right=7
tempL=4; right=7
tempL=0; right=7
排序后:[1, 2, 3, 4, 5, 6, 7, 8]

从这里也可以看到,先左递归的话,可以看到最开始合并的索引是 0,1 也就是在栈顶开始首次递归时:两个数组中分别只有一个数字。

最后一次合并:则是回到了最初栈底开始分解的方法,将两个数组 0到7 进行排序到临时数组 temp ,最后将temp中的数据再从 0到7 覆盖到原始数组中。完成了排序 。

8 个数字,会进行 7 次 合并

结合上面动图进行思考。

对代码的一些改进

根据上述所讲的基本思想和思路分析,对代码进行了一些改进修改,减小代码的臃肿。

public class MyMergeSortTest {
    @Test
    public void sortTest() {
        int[] arr = new int[]{8, 4, 5, 7, 1, 3, 6, 2};
        mergeSort(arr);
        System.out.println("排序后:" + Arrays.toString(arr));
    }

    public void mergeSort(int arr[]) {
        int[] temp = new int[arr.length];
        doMergeSort(arr, 0, arr.length - 1, temp);
    }

    /**
     * 分治 与 合并
     *
     * @param arr
     * @param left
     * @param right
     * @param temp
     */
    private void doMergeSort(int[] arr, int left, int right, int[] temp) {
        // 当还可以分解时,就做分解操作
        if (left < right) {
            int mid = (left + right) / 2;
            // 先左递归分解
            doMergeSort(arr, left, mid, temp);
            // 再右递归分解
            doMergeSort(arr, mid + 1, right, temp);
            // 左递归分解到栈顶时,其实也是分为左右数组
            // 左右都到栈顶时,开始合并:
            // 第一次:合并的是 0,1 的索引,分解到最后的时候,其实只有一个数为一组,所以第一次合并是合并两个数字
            merge(arr, left, mid, right, temp);
        }
    }

    /**
     * 开始合并,每次合并都是两组,第一次合并是两个数字,左右一组都只有一个数字
     *
     * @param arr
     * @param left
     * @param mid
     * @param right
     * @param temp
     */
    private void merge(int[] arr, int left, int mid, int right, int[] temp) {
        // 1. 按照规则,将 temp 数组填充
        // 2. 当任意一边填充完成后,剩余未填充的依次填充到 temp 数组中
        // 3. 将 temp 数组的有效内容,拷贝会原数组,也就是将这次排序好的数组覆盖回原来排序的原数组中

        int l = left; // 左侧数组初始索引
        int r = mid + 1; // 右侧数组初始索引
        int t = 0; // 当前 temp 中有效数据的最后一个元素索引

        // 1. 按照规则,将 temp 数组填充
        // 当两边都还有数字可比较的时候,进行比较,然后填充 temp 数组
        // 只要任意一边没有数值可用时,就仅需到下一步骤
        while (l <= mid && r <= right) {
            // 当左边比右边小时,则填充到 temp 数组中
            if (arr[l] < arr[r]) {
                // 赋值完成后,t 和 l 都需要 +1,往后移动一个位置
                // t++ 是先把 t 进行赋值,再进行 t+1 操作
                temp[t++] = arr[l++];
            } else {
                // 当不满足时,则说明 右侧数字比左侧的小,进行右侧的填充
                temp[t++] = arr[r++];
            }
        }

        // 2. 有可能有其中一边会有剩余数字未填充到 temp 中,进行收尾处理
        while (l <= mid) {
            temp[t++] = arr[l++];
        }
        while (r <= right) {
            temp[t++] = arr[r++];
        }

        // 3. 将这个有序数组,覆盖会原始排序的数组中
        t = 0;
        int tempL = left; // 从左侧开始,到右侧结束,就是这一次要合并的两组数据
        while (tempL <= right) {
            arr[tempL++] = temp[t++];
        }
    }
}

大数据量耗时测试

    /**
     * 大量数据排序时间测试
     */
    @Test
    public void bulkDataSort() {
        int max = 80000;
//        max = 8;
        int[] arr = new int[max];
        for (int i = 0; i < max; i++) {
            arr[i] = (int) (Math.random() * 80000);
        }
        if (arr.length < 10) {
            System.out.println("原始数组:" + Arrays.toString(arr));
        }
        Instant startTime = Instant.now();
        int[] temp = new int[arr.length];
        mergeSort(arr, 0, arr.length - 1, temp);
        if (arr.length < 10) {
            System.out.println("排序后:" + Arrays.toString(arr));
        }
        Instant endTime = Instant.now();
        System.out.println("共耗时:" + Duration.between(startTime, endTime).toMillis() + " 毫秒");
    }

多次测试输出

共耗时:26 毫秒
共耗时:37 毫秒
共耗时:30 毫秒
共耗时:30 毫秒

复杂度

归并排序比较占用内存,但却是一种效率高且稳定的算法。

改进归并排序在归并时先判断前段序列的最大值与后段序列最小值的关系再确定是否进行复制比较。如果前段序列的最大值小于等于后段序列最小值,则说明序列可以直接形成一段有序序列不需要再归并,反之则需要。所以在序列本身有序的情况下时间复杂度可以降至O(n)。

TimSort可以说是归并排序的终极优化版本,主要思想就是检测序列中的天然有序子段(若检测到严格降序子段则翻转序列为升序子段)。在最好情况下无论升序还是降序都可以使时间复杂度降至为O(n),具有很强的自适应性。

最好时间复杂度 最坏时间复杂度 平均时间复杂度 空间复杂度 稳定性
传统归并排序 O(nlogn) O(nlogn) O(nlogn) T(n) 稳定
改进归并排序 [1] O(n) O(nlogn) O(nlogn) T(n) 稳定
TimSort O(n) O(nlogn) O(nlogn) T(n) 稳定

我个人感觉归并排序的逻辑相比快速排序来说更为容易理解,而且时间复杂度和快排一样。关于快排的有关讲解请看 java 排序算法之快速排序。

到此这篇关于java 排序算法之归并排序的文章就介绍到这了,更多相关java 归并排序内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java分治归并排序算法实例详解

    本文实例讲述了Java分治归并排序算法.分享给大家供大家参考,具体如下: 1.分治法 许多有用的算法在结构上是递归的:为了解决一个给定的问题,算法一次或多次递归地调用其自身以解决紧密相关的若干子问题.这些算法典型地遵循分治法的思想:将原问题分解为几个规模较小但类似于原问题的子问题,递归地求解这些子问题,然后再合并这些子问题的解来建立原问题的解. 分治模式在每层递归时都有三个步骤: (1)分解原问题为若干子问题,这些子问题是原问题的规模较小的实例. (2)解决这些子问题,递归地求解各子问题.然而,

  • JAVA十大排序算法之归并排序详解

    目录 归并排序 怎么分 怎么治 代码实现 时间复杂度 算法稳定性 总结 归并排序 归并,指合并,合在一起.归并排序(Merge Sort)是建立在归并操作上的一种排序算法.其主要思想是分而治之.什么是分而治之?分而治之就是将一个复杂的计算,按照设定的阈值进行分解成多个计算,然后将各个计算结果进行汇总.即"分"就是把一个大的通过递归拆成若干个小的,"治"就是将分后的结果在合在一起. 若将两个有序集合并成一个有序表,称为2-路归并,与之对应的还有多路归并. 怎么分 对于

  • Java 归并排序算法、堆排序算法实例详解

    基本思想: 归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的.然后再把有序子序列合并为整体有序序列. 归并排序示例: 合并方法: 设r[i-n]由两个有序子表r[i-m]和r[m+1-n]组成,两个子表长度分别为n-i +1.n-m. j=m+1:k=i:i=i; //置两个子表的起始下标及辅助数组的起始下标 若i>m 或j>n,转⑷ //其中一个子表已合并完,比较选取结束 //选取r[i]和r[j]较小的存入辅助数组

  • Java排序算法之归并排序简单实现

    算法描述:对于给定的一组记录,首先将每两个相邻的长度为1的子序列进行归并,得到 n/2(向上取整)个长度为2或1的有序子序列,再将其两两归并,反复执行此过程,直到得到一个有序序列. package sorting; /** * 归并排序 * 平均O(nlogn),最好O(nlogn),最坏O(nlogn);空间复杂度O(n);稳定;较复杂 * @author zeng * */ public class MergeSort { public static void merge(int[] a,

  • java 中归并排序算法详解

    java 中归并排序算法详解 归并排序算法,顾名思义,是一种先分再合的算法,其算法思想是将要排序的数组分解为单个的元素,每个元素就是一个单个的个体,然后将相邻的两个元素进行从小到大或从大到小的顺序排序组成一个整体,每个整体包含一到两个元素,然后对相邻的整体继续"合"并,因为每个整体都是排过序的,因而可以采用一定的算法对其进行合并,合并之后每个整体包含三到四个元素,继续对相邻的整体进行合并,直到所有的整体都合并为一个整体,最终得到的整体就是将原数组进行排序之后的结果. 对于相邻的整体,其

  • Java排序算法三之归并排序的递归与非递归的实现示例解析

    归并有递归和非递归两种. 归并的思想是: 1.将原数组首先进行两个元素为一组的排序,然后合并为四个一组,八个一组,直至合并整个数组: 2.合并两个子数组的时候,需要借助一个临时数组,用来存放当前的归并后的两个数组: 3.将临时数组复制回原数组对应的位置. 非递归的代码如下: package mergesort; import java.util.Arrays; import java.util.Random; import java.util.Scanner; //归并排序的非递归算法 publ

  • java数据结构排序算法之归并排序详解

    本文实例讲述了java数据结构排序算法之归并排序.分享给大家供大家参考,具体如下: 在前面说的那几种排序都是将一组记录按关键字大小排成一个有序的序列,而归并排序的思想是:基于合并,将两个或两个以上有序表合并成一个新的有序表 归并排序算法:假设初始序列含有n个记录,首先将这n个记录看成n个有序的子序列,每个子序列长度为1,然后两两归并,得到n/2个长度为2(n为奇数的时候,最后一个序列的长度为1)的有序子序列.在此基础上,再对长度为2的有序子序列进行亮亮归并,得到若干个长度为4的有序子序列.如此重

  • Java经典排序算法之归并排序详解

    一.归并排序 归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用.将已有序的子序列合并,得到完全有序的序列:即先使每个子序列有序,再使子序列段间有序.若将两个有序表合并成一个有序表,称为二路归并. 归并过程为:比较a[i]和a[j]的大小,若a[i]≤a[j],则将第一个有序表中的元素a[i]复制到r[k]中,并令i和k分别加上1:否则将第二个有序表中的元素a[j]复制到r[k]中,并令j和k分别加上1,如此循环下去,直

  • java 排序算法之归并排序

    目录 简单介绍 基本思想 思路分析 代码实现 对代码的一些改进 大数据量耗时测试 复杂度 简单介绍 归并排序(merge sort)是利用 归并 的思想实现的排序方法,该算法采用经典的 分治(divide-and-conquer)策略 : 分(divide):将问题分成一些小的问题,然后递归求解 治(conquer):将分的阶段得到的各答案「修补」在一起 即:分而治之 该算法是采用分治法(Divide and Conquer)的一个非常典型的应用.将已有序的子序列合并,得到完全有序的序列:即先使

  • 图解Java排序算法之归并排序

    目录 基本思想 合并相邻有序子序列 代码实现 总结 基本思想 归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之). 分而治之 可以看到这种结构很像一棵完全二叉树,本文的归并排序我们采用递归去实现(也可采用迭代的方式去实现).分阶段可以理解为就是递归拆分子序列的过程,递归深

  • Java排序算法总结之归并排序

    本文实例讲述了Java排序算法总结之归并排序.分享给大家供大家参考.具体分析如下: 归并操作(merge),也叫归并算法,指的是将两个已经排序的序列合并成一个序列的操作.和快速排序类似,让我们一起来看,归并在Java中的实现. 归并排序(Merge)是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的.然后再把有序子序列合并为整体有序序列. 归并排序是建立在归并操作上的一种有效的排序算法.该算法是采用分治法(Divide and Conquer)的

  • Java 十大排序算法之归并排序刨析

    目录 归并排序原理 归并排序API设计 归并排序代码实现 归并排序的时间复杂度分析 归并排序原理 1.尽可能的一组数据拆分成两个元素相等的子组,并对每一个子组继续拆分,直到拆分后的每个子组的元素个数是1为止. ⒉将相邻的两个子组进行合并成一个有序的大组. 3.不断的重复步骤2,直到最终只有一个组为止. 归并排序API设计 类名 Merge 构造方法 Merge():创建Merge对象 成员方法 1.public static void sort(Comparable[] a):对数组内的元素进行

  • Java排序算法总结之冒泡排序

    本文实例讲述了Java排序算法总结之冒泡排序.分享给大家供大家参考.具体分析如下: 前言:冒泡排序(BubbleSort)就是依次比较相邻的两个数,将小数放在前面,大数放在后面. 下面让我们一起    来看冒泡排序在Java中的算法实现. 冒泡排序是计算机的一种排序方法,它的时间复杂度为O(n^2),虽然不及堆排序.快速排序的O(nlogn,底数为2),但是有两个优点: 1."编程复杂度"很低,很容易写出代码: 2.具有稳定性,这里的稳定性是指原序列中相同元素的相对顺序仍然保持到排序后

  • java 基本算法之归并排序实例代码

    java 基本算法之归并排序实例代码 原理:归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表, * 即把待排序序列分为若干个子序列,每个子序列是有序的.      * 然后再把有序子序列合并为整体有序序列. 实例代码: public class MergeSort { /** * * * * @param args */ public static void main(String[] args) { int a[] = { 49, 38, 65, 97, 76, 13,

  • 盘点几种常见的java排序算法

    目录 1.插入排序 2.分治排序法,快速排序法 3.冒泡排序 low版 4.冒泡排序 bigger版 5.选择排序 6. 归并排序 8. 堆排序 9. 其他排序 10. 比较 总结 1.插入排序 这个打麻将或者打扑克的很好理解, 比如有左手有一副牌1,2,4,7 ,来一张3的牌, 是不是就是手拿着这张牌从右往左插到2,4之间 一次插入排序的操作过程: 将待插元素,依次与已排序好的子数列元素从后到前进行比较,如果当前元素值比待插元素值大,则将移位到与其相邻的后一个位置,否则直接将待插元素插入当前元

随机推荐