java 排序算法之快速排序

目录
  • 简单介绍
  • 基本思想
  • 思路分析
  • 代码实现
    • 推导实现
    • 完整实现
  • 大数据量耗时测试
  • 性能分析

简单介绍

快速排序(Quicksort) 是对 冒泡排序的一种改进。

基本思想

快速排序算法通过多次比较和交换来实现排序,其排序流程如下:

  • (1)首先设定一个分界值(基准值),通过该分界值将数组分成左右两部分。
  • (2)将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于或等于分界值,而右边部分中各元素都大于或等于分界值。
  • (3)然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。
  • (4)重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了。

该思想可以概括为:挖坑填数 + 分治法。

比如如下的示意图:

  • 上图以 最后一个元素的值 作为基准
  • 比基准值小的,排在左侧,比基准值大的排在右侧
  • 然后再以分好的部分重复以上操作,直到每个部分中只有一个数据时,就排好序了

思路分析

基本思想如上,但是实现思路有多种,一般取基准值都是以首尾或者中间,这里使用 数组中间 的作为基准值,进行讲解。

  • 原始数组:arr = [-9,78,0,23,-567-70]

  • 设置两个变量,左下标L = 0,右下标R = 数组大小 - 1,选数组中间的值为基准值,pivot = arr[(L + R )/ 2] ,基准值为 0。再用两个变量保存 左下标 和 右下标,left = Lright = R,用于后面的排序做准备。

可以看到,pivot把数组分成了两组

  • 左边一组,从左到右,挨个与 基准值 比较,找出比基准值大的值,跳出查找循环

  • 右边一组,从右到左,挨个与 基准值 比较,找出比基准值小的值,跳出查找循环

  • 可以看到左右两组各找到一个对应的值,那么就让他们进行交换

  • 然后继续找,直到左右两边碰到,

可以看到左边的组已经找完了,L指向了基准值,那就跳出查找循环,右边组开始查找,

但是我们可以看到右边的数也都符合规则,所以R也循环遍历到了基准值的位置,此时LR 已经碰到一起了,这一轮就结束。这一轮就称为快速排序。

继续对分出来的小组,进行上述的快速排序操作,直到组内只剩下一个数时,则排序完成。

  • LR 分别前进一步和后退一步,

如图,就可以再次利用这两个变量,对两组进行快速排序了。

  • 先对左边的组进行快速排序,同样进行上面的操作,

这里就用到了上一次快速循环所保存的leftright(上图没有画出来)了。

  • 因为这里 left 直接就指向了 pivot ,所以不用进行移动查找了。Rpivot进行比较 ,-567 < -9 ,Rleft进行交换,得到如下图,注:pivot 是一个值,不是引用类型

因为 Rleft 没有碰头,所以还得进行一次循环比较。因为 R 就在基准点这,所以不移动,Rpivot 比较,-9 > -567 , 所以left 前进一步,

此时Rleft 已经碰到一起了,这一轮就结束了。

  • 右边的组也是同样的道理,这里就不作过多的解析了

l ------------ pivot --------------- r
一组从左往右找               一组从右往左找

可以看到,分组后,可以使用递归,对这一组继续分组,然后对他们进行快速排序。

代码实现

推导实现

推导法先实现第一轮

    @Test
    public void processDemo() {
        int arr[] = {-9, 78, 0, 23, -567, 70};
        System.out.println("原始数组:" + Arrays.toString(arr));
        processQuickSort(arr, 0, arr.length - 1);
    }

    /**
     * @param arr
     * @param left  左边这一组的下标起始点,到中间值,则为一组
     * @param right 右边这一组的下标结束点,到中间值,则为一组
     */
    public void processQuickSort(int[] arr, int left, int right) {
        /*
         基本思想:选择一个基准值,将基准值小分成一组,比基准值大的分成一组。
         这里的实现思路:
            1. 挑选的基准值为数组中间的值
            2. 中间值就把数组分成了两组
            3. 左边一组,从左到右,挨个与 基准值 比较,找出比基准值大的值
            4. 右边一组,从右到左,挨个与 基准值 比较,找出比基准值小的值
            5. 左右两边各找到一个值,那么就让这两个值进行交换
            6. 然后继续找,直到左右两边碰到,这一轮就结束。这一轮就称为快速排序
            7. 继续对分出来的小组,进行上述的快速排序操作,直到组内只剩下一个数时,则排序完成

            l ------------ pivot --------------- r
            一组从左往右找               一组从右往左找
         */
        int l = left;
        int r = right;
        // 中心点,让这个点作为基准值
        int pivot = arr[(left + right) / 2];
        // 当他们没有碰到的时候,说明还这一轮还可以继续找
        while (l < r) {
            // 左边组:当找到大于基准值时,退出循环,则表示该值需要交换到右侧去: arr[l] > pivot
            //      也就是说,如果 arr[l] < pivot,则表示还没有找到比基准值大的数
            //      注意:不能等于 pivort,因为最差的情况没有找到,则最后 arr[l] 就是 pivot 这个值,也同样退出循环
            while (arr[l] < pivot) {
                l++; // 所以让左边这一组继续找
            }

            // 右边组:当找到小于基准值时,退出循环,则表示该值需要交换到左侧去:arr[r] < pivot
            //      也就是说,如果 arr[l] > pivot,则表示还没有找到比基准值小的数
            //注意:这里也同样跟上面一样,不能等于 pivort
            while (arr[r] > pivot) {
                r--;//让右边组继续找
            }

            // 当左侧与右侧相碰时,说明两边都没有找到,这一轮不用进行交换
            // 等于表示,找到了中间的下标
            if (l >= r) {
                break;
            }

            // 当找到时,则两数进行交换。
            //注意:这里可能会出现有一组已经找完了,或者没有找到,但是另一组找到了,所以一个是指向 pivot 的,
            //另一个则是指向要交换的数,交换后 pivot的值在数组中的位置会发生改变,下次的交换方式就会发生变化。这个地方要动脑筋想想。
            int temp = arr[l];
            arr[l] = arr[r];
            arr[r] = temp;

            // 当交换后,
            // 当数组是: {-9, 78, 0, -23, 0, 70}  时(pivot的值在数组中有多个),就可以验证这里的逻辑
            // 如果没有这个判定,将会导致,l 永远 小于 r。循环不能退出来的情况,就出现死循环了
            if (arr[l] == pivot) {
                /*
                  l 自己不能往前移动 一步,因为当交换完成后为:{-9, 0, 0, -23, 78, 70}
                  l = 1,arr[l] = 0
                  r = 4,arr[r] = 78
                  再经过一次循环后
                  l = 1,arr[l] = 0
                  r = 3,arr[r] = -23
                  交换后数组为:{-9,-23,0,0,78,70}
                  此时 l = 1,arr[l] = -23;r = 3,arr[r] = 0
                  又经过一次循环后
                  l = 2,arr[l] = 0
                  r = 3,arr[r] = 0
                  数组为:{-9,-23,0,0,78,70}
                  进入了死循环
                  这里好好动脑子想想

                  这里为什么是用r-=1呢?是因为if里面的条件是arr[l] == pivot,如果要排序的数组中不存在多个和基准值相等的值,
                  那么用l+=1的话,l就会跑过分界线(基准值),跑到另一组去,这个算法也就失败了,
                  还有一个原因是,r 是刚刚交换过的,一定比 基准值大,所以没有必要再和基准值比较了
                 */
                r -= 1;
            }
            // 这里和上面一致,如果说,先走了上面的 r-=1
            // 这里也满足(也就是说有多个值和基准值相等),那么说明,下一次是相同的两个值,一个是 r == 一个是基准值
            // 但是他们是相同的值,r后退一步 l前进一步,不影响。但是再走这完这里逻辑时,就会导致  l > r,退出整个循环
            if (arr[r] == pivot) {
                l += 1;
            }
        }
        System.out.println("第 1 轮排序后:" + Arrays.toString(arr));
    }

注意:上述的算法特别是边界判定,就是上面「当交换后」对 r-=1 的这个边界判定时,有点难以理解,但是一定要理解为什么要这样写。

测试信息输出

原始数组:[-9, 78, 0, 23, -567, 70]
第 1 轮排序后:[-9, -567, 0, 23, 78, 70]

那么如何向左递归和右递归呢?在上面的代码后面接着实现如下

        System.out.println("第 1 轮排序后:" + Arrays.toString(arr));

		/*
		if (l >= r) {
                break;
            }
            循环从这条代码中跳出就会l = r
		*/
        // 如果 l = r,会出现死循环,出现栈溢出
		//这里也要动脑子想想
        if (l == r) {
            l++;
            r--;
        }

        // 开始左递归
        // 上面算法是 r--,l++ ,往两组的中间走,当 left < r 时,表示还可以继续分组
        if (left < r) {
            processQuickSort(arr, left, r);
        }

        if (right > l) {
            processQuickSort(arr, l, right);
        }

完整实现

完整实现和推导实现其实差不多了,为了加深记忆,自己按照基本思想和思路分析,默写。

  /**
     * 快速排序默写实现
     *
     *     基本思想:通过一趟将要排序的数据,分隔成独立的两个部分,一部分的所有数据都比另一部分的所有数据要小。
     *     思路分析:
     *      {-9, 78, 0, 23, -567, 70};  length=6
     *      1. 挑选中间的值作为 基准值:(0 + (6 -1))/2= [2] = 0
     *      2. 左侧 left 部分,从 0 开始到中间值 -1: 0,1: -9, 78,找出一个比基准值大的数
     *      3. 右侧 right 部分,从中间值 + 1 到数组大小-1:3,5:23,-567, 70,找出一个比基准值小的数
     *      4. 如果找到,则将他们进行交换,这样一轮下来,就完成了一次快速排序:一部分的所有数据都比另一部分的所有数据要小。
     *      4. 如果左侧部分还可以分组,则进行左侧递归调用
     *      5. 如果右侧部分还可以分组,则进行右侧递归调用
     *
     *    简单说:一轮快速排序示意图如下:
     *                   中间的基准值
     *      l ------------ pivot --------------- r
     *      一组从左往右找               一组从右往左找
     *      找到比基准值大的数          找出一个比基准值小的数
     *                    然后进行交换
     *
     */
    @Test
    public void quickSortTest() {
        int arr[] = {-9, 78, 0, 23, -567, 70};
//        int arr[] = {-9, 78, 0, -23, 0, 70}; // 在推导过程中,将会导致交换异常的数组,在这里不会出现那种情况
        int left = 0;
        int right = arr.length - 1;
        System.out.println("原始数组:" + Arrays.toString(arr));
        quickSort(arr, left, right);
        System.out.println("排序后:" + Arrays.toString(arr));
    }

    public void quickSort(int[] arr, int left, int right) {
        // 找到中间值
        int pivotIndex = (left + right) / 2;
        int pivot = arr[pivotIndex];
        int l = left;
        int r = right;
        while (l < r) {
            // 从左往右找,直到找到一个数,比基准值大的数
            while (arr[l] < pivot) {
                l++;
            }
            // 从右往左找,知道找到一个数,比基准值小的数
            while (arr[r] > pivot) {
                r--;
            }
            // 表示未找到
            if (l >= r) {
                break;
            }
            // 进行交换
            int temp = arr[l];
            arr[l] = arr[r];
            arr[r] = temp;

            // 那么下一轮,左侧的这个值将不再参与排序,因为刚交换过,一定比基准值小
            // 那么下一轮,右侧的这个值将不再参与排序,因为刚交换过,一定比基准值大
            r--;
            l++;
        }

        // 当一轮找完后,没有找到,则是中间值时,
        // 需要让他们擦肩而过,也就是重新分组,中间值不再参与分组
        // 否则,在某些情况下,会进入死循环
        if (l == r) {
            l++;
            r--;
        }
        // 如果左侧还可以继续分组,则继续快排
        // 由于擦肩而过了,那么左侧的组值,则是最初的开始与中间值的前一个,也就是这里得到的 r
        if (left < r) {
            quickSort(arr, left, r);
        }
        if (right > l) {
            quickSort(arr, l, right);
        }
    }

另外,在实现的过程中,将某些代码为什么要那样判断边界,进行了梳理。你会发现上述代码和推导的代码有一个地方不一样。这个是我自己按逻辑进行的改进,更容易看明白一些。目前未发现 bug,如果有错请评论指出,毕竟这个算法还是有点难的。

大数据量耗时测试

    /**
     * 大量数据排序时间测试
     */
    @Test
    public void bulkDataSort() {
        int max = 80000;
//        int 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();
//        processQuickSort(arr, 0, arr.length - 1);  // 和老师的原版代码对比,结果是一样的
        quickSort(arr, 0, arr.length - 1);
        if (arr.length < 10) {
            System.out.println("排序后:" + Arrays.toString(arr));
        }
        Instant endTime = Instant.now();
        System.out.println("共耗时:" + Duration.between(startTime, endTime).toMillis() + " 毫秒");
    }

多次运行输出

共耗时:40 毫秒
共耗时:52 毫秒
共耗时:36 毫秒
共耗时:31 毫秒

性能分析

快速排序的一次划分算法从两头交替搜索,直到low和hight重合,因此其时间复杂度是O(n);而整个快速排序算法的时间复杂度与划分的趟数有关。

理想的情况是,每次划分所选择的中间数恰好将当前序列几乎等分,经过log2n趟划分,便可得到长度为1的子表。这样,整个算法的时间复杂度为O(nlog2n)。

最坏的情况是,每次所选的中间数是当前序列中的最大或最小元素,这使得每次划分所得的子表中一个为空表,另一子表的长度为原表的长度-1。这样,长度为n的数据表的快速排序需要经过n趟划分,使得整个排序算法的时间复杂度为O(n2)。

为改善最坏情况下的时间性能,可采用其他方法选取中间数。通常采用“三者值取中”方法,即比较H->r[low].key、H->r[high].key与H->r[(low+high)/2].key,取三者中关键字为中值的元素为中间数。

可以证明,快速排序的平均时间复杂度也是O(nlog2n)。因此,该排序方法被认为是目前最好的一种内部排序方法。

从空间性能上看,尽管快速排序只需要一个元素的辅助空间,但快速排序需要一个栈空间来实现递归。最好的情况下,即快速排序的每一趟排序都将元素序列均匀地分割成长度相近的两个子表,所需栈的最大深度为log2(n+1);但最坏的情况下,栈的最大深度为n。这样,快速排序的空间复杂度为O(log2n)。

以上就是java 排序算法之快速排序的详细内容,更多关于java 快速排序的资料请关注我们其它相关文章!

(0)

相关推荐

  • java实现快速排序算法

    1.算法概念. 快速排序(Quicksort)是对冒泡排序的一种改进.由C. A. R. Hoare在1962年提出. 2.算法思想. 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列. 3.实现思路. ①以第一个关键字 K 1 为控制字,将 [K 1 ,K 2 ,-,K n ] 分成两个子区,使左区所有关键字小于等于 K 1 ,右区所有关键字大于

  • 浅析java快速排序算法

    快速排序是找出一个元素(理论上可以随便找一个)作为基准(pivot),然后对数组进行分区操作,使基准左边元素的值都不大于基准值,基准右边的元素值 都不小于基准值,如此作为基准的元素调整到排序后的正确位置.递归快速排序,将其他n-1个元素也调整到排序后的正确位置.最后每个元素都是在排序后的正 确位置,排序完成.所以快速排序算法的核心算法是分区操作,即如何调整基准的位置以及调整返回基准的最终位置以便分治递归. 一趟快速排序的算法是: 1)设置两个变量i.j,排序开始的时候:i=0,j=N-1: 2)

  • 快速排序算法在Java中的实现

    快速排序的原理:选择一个关键值作为基准值.比基准值小的都在左边序列(一般是无序的),比基准值大的都在右边(一般是无序的).一般选择序列的第一个元素. 一次循环:从后往前比较,用基准值和最后一个值比较,如果比基准值小的交换位置,如果没有继续比较下一个,直到找到第一个比基准值小的值才交换.找到这个值之后,又从前往后开始比较,如果有比基准值大的,交换位置,如果没有继续比较下一个,直到找到第一个比基准值大的值才交换.直到从前往后的比较索引>从后往前比较的索引,结束第一次循环,此时,对于基准值来说,左右两

  • 快速排序算法原理及java递归实现

    快速排序 对冒泡排序的一种改进,若初始记录序列按关键字有序或基本有序,蜕化为冒泡排序.使用的是递归原理,在所有同数量级O(n longn) 的排序方法中,其平均性能最好.就平均时间而言,是目前被认为最好的一种内部排序方法 基本思想是:通过一躺排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列. 三个指针: 第一个指针称为pivotkey指针(枢轴),第二个指

  • JAVA十大排序算法之快速排序详解

    目录 快速排序 问题 思路 荷兰国旗问题 代码实现 时间复杂度 算法稳定性 总结 快速排序 快速排序是对冒泡排序的一种改进,也是采用分治法的一个典型的应用.JDK中Arrays的sort()方法,具体的排序细节就是使用快速排序实现的. 从数组中任意选取一个数据(比如数组的第一个数或最后一个数)作为关键数据,我们称为基准数(pivot,或中轴数),然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序,也称为分区(partition)操作. 问题 若给定一个无序数组

  • Java编程中快速排序算法的实现及相关算法优化

    时间复杂度 平均情况:O(nlgn) 最坏情况:O(n*n),发生在当数据已经是排序状态时 快排算法的基本原理 1.从数据中选取一个值a[i]作为参考 2.以a[i] 为参考,将数据分成2部分:P1.P2,P1中的数据全部≤a[i],P2中的数据全部>a[i],数据变为{{P1}{a[i]}{P2}} 3.将P1.P2重复上述步骤,直到各部分中只剩1个数据 4.数据完成升序排列 基本示例: 原始数据: {3,9,8,5,2,1,6} 第1步:选取第1个数据:3 第2步:将数据分成2部分,左边≤3

  • Java实现快速排序算法的完整示例

    首先,来看一下,快速排序的实现的动态图: 快速排序介绍: 快速排序,根据教科书说法来看,是冒泡排序的一种改进. 快速排序,由一个待排序的数组(array),以及找准三个变量: 中枢值(pivot) 左值(left) 右值(right) 根据中枢值(pivot)来做调整,将数组(array)分为三个部分: 第一部分:中枢值(pivot),单独数字构成,这个值在每次排序好的"最中间": 第二部分:左边数组(由array的一部分组成),这个数组在第一部分 中枢值(pivot) 的"

  • JAVA版排序算法之快速排序示例

    本文实例讲述了JAVA快速排序实现方法.分享给大家供大家参考,具体如下: package com.ethan.sort.java; import java.util.Arrays; import java.util.Iterator; import java.util.LinkedList; import java.util.List; public class QuickSort { public static <E extends Comparable<? super E>>

  • java 排序算法之快速排序

    目录 简单介绍 基本思想 思路分析 代码实现 推导实现 完整实现 大数据量耗时测试 性能分析 简单介绍 快速排序(Quicksort) 是对 冒泡排序的一种改进. 基本思想 快速排序算法通过多次比较和交换来实现排序,其排序流程如下: (1)首先设定一个分界值(基准值),通过该分界值将数组分成左右两部分. (2)将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边.此时,左边部分中各元素都小于或等于分界值,而右边部分中各元素都大于或等于分界值. (3)然后,左边和右边的数据可以

  • 图解Java排序算法之快速排序的三数取中法

    目录 基本步骤 三数取中 根据枢纽值进行分割 代码实现 总结 基本步骤 三数取中 在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分.在此我们采用三数取中法,也就是取左端.中间.右端三个数,然后进行排序,将中间数作为枢纽值. 根据枢纽值进行分割 代码实现 package sortdemo; import java.util.Arrays; /** * Created by chengxiao on 2016/12/14. * 快速排序 */ public class

  • java 排序算法之归并排序

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

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

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

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

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

  • Java排序算法总结之希尔排序

    本文实例讲述了Java排序算法总结之希尔排序.分享给大家供大家参考.具体分析如下: 前言:希尔排序(Shell Sort)是插入排序的一种.是针对直接插入排序算法的改进.该方法又称缩小增量排序,因DL.Shell于1959年提出而得名.本文主要介绍希尔排序用Java是怎样实现的. 希尔排序(缩小增量法) 属于插入类排序,是将整个无序列分割成若干小的子序列分别进行插入排序.希尔排序并不稳定,O(1)的额外空间,时间复杂度为O(N*(logN)^2).最坏的情况下的执行效率和在平均情况下的执行效率相

  • java 排序算法之希尔算法

    目录 插入排序存在的问题 简单介绍 基本思想 代码实现 大数据量耗时测试 移动法实现希尔排序 移动法-大数据量耗时测试 算法分析 注:学习本篇的前提是要会插入排序,数据结构与算法--排序算法-插入排序 插入排序存在的问题 简单的插入排序可能存在的问题. 如数组 arr = {2,3,4,5,6,1} 这时需要插入的数 1(最小),过程是: 展示的是要移动 1 这个数,的过程,由于在最后,需要前面的所有数都往后移动一位 {2,3,4,5,6,6} {2,3,4,5,5,6} {2,3,4,4,5,

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

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

  • Java排序算法之SleepSort排序示例

    本文实例讲述了Java排序算法之SleepSort排序.分享给大家供大家参考,具体如下: 分享一个很有创意的排序算法:sleepSort .巧妙利用了线程的sleep(),代码如下: public class SleepSort { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub int[] ints = {1,4,7,3,8,9,2,6,5}; So

  • Java排序算法总结之选择排序

    本文实例讲述了Java排序算法总结之选择排序.分享给大家供大家参考.具体分析如下: 选择排序的基本操作就是每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完.算法不稳定,O(1)的额外的空间,比较的时间复杂度为O(n^2),交换的时间复杂度为O(n),并不是自适应的.在大多数情况下都不推荐使用.只有在希望减少交换次数的情况下可以用.   基本思想   n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果: ①初始状态:

随机推荐