经典排序方法

一、

冒泡排序:

(1)原理:

  1、从第一个数据开始,与第二个数据相比较,如果第二个数据小于第一个数据,则交换两个数据的位置。

  2、指针由第一个数据移向第二个数据,第二个数据与第三个数据相比较,如果第三个数据小于第二个数据,则交换两个数据的位置。

  3、依此类推,完成第一轮排序。第一轮排序结束后,最大的元素被移到了最右面。

  4、依照上面的过程进行第二轮排序,将第二大的排在倒数第二的位置。

  5、重复上述过程,没排完一轮,比较次数就减少一次。

(2)例子:

待排序数据:7, 6, 9, 8, 5,1

第一轮排序过程:指针先指向7,7和6比较,6<7,交换6和7的位置,结果为:6,7,9,8,5,1

        指针指向第二个元素7,7和9比较,9>7,不用交换位置,结果仍为:6,7,9,8,5,1

        指针指向第三个元素9,比较9和8,8<9,交换8和9的位置,结果为:6,7,8,9,5,1

        指针指向第四个元素9,比较9和5,5<9,交换5和9,结果为:6,7,8,5,9,1

        指针指向第五个元素9,比较9和1,1<9,交换1和9的位置,结果为6,7,8,5,1,9

第一轮排序结束后,最大的数字9被移到了最右边。

进行第二轮排序,过程同上,只是由于最大的9已经放在最右边了,因此不用在比较9了,少了一次比较,第二轮结束的结果为:6,7,5,1,8,9

第三轮结果:6,5,1,7,8,9

第四轮比较结果:5,1,6,7,8,9

第五轮比较结果:1,5,6,7,8,9

最终排序结果为:1,5,6,7,8,9,由上可知N个数据排序,需要进行N-1轮排序;第i轮排序需要的比较次数为N-i次。

    /**
     * 冒泡排序
     *
     * @param arr
     * @return
     */
    public static int[] maopao(int... arr) {
        int m = 0;
        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]) {
                    int f = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = f;
                }
                m++;
            }
        }
        System.out.println("冒泡排序 m=" + m);
        return arr;
    }

二、

选择排序

  选择排序是对冒泡排序的改进,它的比较次数与冒泡排序相同,但交换次数要小于冒泡排序。当数据量较大时,效率会有很大的提升,但时间复杂度仍为O(n*n)

(1)原理:

  1、从第一个元素开始,分别与后面的元素向比较,找到最小的元素与第一个元素交换位置;

  2、从第二个元素开始,分别与后面的元素相比较,找到剩余元素中最小的元素,与第二个元素交换;

  3、重复上述步骤,直到所有的元素都排成由小到大为止。

(2)例子:

  待比较数据:7, 6, 9, 8, 5,1

  第一轮:此时指针指向第一个元素7,找出所有数据中最小的元素,即1,交换7和1的位置,排序后的数据为:1,6,9,8,5,7

  第二轮:第一个元素已经为最小的元素,此时指针指向第二个元素6,找到6,9,8,5,7中最小的元素,即5,交换5和6的位置,排序后的结果为:1,5,9,8,6,7

  第三轮:前两个元素为排好序的元素,此时指针指向第三个元素9,找到9,8,6,7中最小的元素,即6,交换6和9的位置,排序后的结果为:1,5,6,8,9,7

  第四轮:前三个元素为排好序的元素,此时指针指向第四个元素8,找到8,9,7中最小的元素,即7,交换8和7的位置,排序后的结果为:1,5,6,7,9,8

  第五轮:前四个元素为排好序的元素,此时指针指向第五个元素9,找到9,8中最小的元素,即8,交换9和8的位置,排序后的结果为:1,5,6,7,8,9

  到此,全部排序完成。

  分析:从上面的原理可以看出,与冒泡排序不同,选择排序每排完一轮都把最小的元素移到了最左面,然后下一轮排序的比较次数比上一轮减少一次,即第i轮排序需要比较N-i次。因此,和冒泡排序一样,N个数据比较大小,需要排序N-1轮,第i轮排序需要比较N-i次。

/**
     * 选择排序
     *
     * @param a
     * @return
     */
    public static int[] xuanze(int... a) {
        int m = 0;
        for (int i = 0; i < a.length - 1; i++) {
            for (int j = i + 1; j < a.length; j++) {
                if (a[i] > a[j]) {
                    int f = a[i];
                    a[i] = a[j];
                    a[j] = f;
                }
                m++;
            }
        }
        System.out.println("选择排序 m=" + m);
        return a;
    }

三、

插入排序

  插入排序是简单排序中最快的排序算法,虽然时间复杂度仍然为O(n*n),但是却比冒泡排序和选择排序快很多。

(1)原理:

  1、将指针指向某个元素,假设该元素左侧的元素全部有序,将该元素抽取出来,然后按照从右往左的顺序分别与其左边的元素比较,遇到比其大的元素便将元素右移,直到找到比该元素小的元素或者找到最左面发现其左侧的元素都比它大,停止;

       2、此时会出现一个空位,将该元素放入到空位中,此时该元素左侧的元素都比它小,右侧的元素都比它大;

  3、指针向后移动一位,重复上述过程。每操作一轮,左侧有序元素都增加一个,右侧无序元素都减少一个。

(2)例子:
  待比较数据:7, 6, 9, 8, 5,1

  第一轮:指针指向第二个元素6,假设6左面的元素为有序的,将6抽离出来,形成7,_,9,8,5,1,从7开始,6和7比较,发现7>6。将7右移,形成_,7,9,8,5,1,6插入到7前面的空位,结果:6,7,9,8,5,1

  第二轮:指针指向第三个元素9,此时其左面的元素6,7为有序的,将9抽离出来,形成6,7,_,8,5,1,从7开始,依次与9比较,发现9左侧的元素都比9小,于是无需移动,把9放到空位中,结果仍为:6,7,9,8,5,1

  第三轮:指针指向第四个元素8,此时其左面的元素6,7,9为有序的,将8抽离出来,形成6,7,9,_,5,1,从9开始,依次与8比较,发现8<9,将9向后移,形成6,7,_,9,5,1,8插入到空位中,结果为:6,7,8,9,5,1

  第四轮:指针指向第五个元素5,此时其左面的元素6,7,8,9为有序的,将5抽离出来,形成6,7,8,9,_,1,从9开始依次与5比较,发现5比其左侧所有元素都小,5左侧元素全部向右移动,形成_,6,7,8,9,1,将5放入空位,结果5,6,7,8,9,1。

  第五轮:同上,1被移到最左面,最后结果:1,5,6,7,8,9。

 /**
     * 插入排序
     *
     * @param arr
     * @return
     */
    public static int[] charu(int... arr) {
        int m = 0;
        for (int index = 1; index < arr.length; index++) {
            int f = arr[index];
            int leftIndex = index - 1;
            while (leftIndex >= 0 && f < arr[leftIndex]) {
                arr[leftIndex + 1] = arr[leftIndex];
                leftIndex--;
                m++;
            }
            arr[leftIndex + 1] = f;
        }
        System.out.println("插入排序 m=" + m);
        return arr;
    }

四、

快速排序

快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

 

 

算法原理

单单看以上解释还是有些模糊,可以通过实例来理解它,下面通过一组数据来进行排序过程的解析:

原数组:{3,7,2,9,1,4,6,8,10,5}

期望结果:{1,2,3,4,5,6,7,8,9,10}

 

花了点时间撸了下面这张快速排序示意图

 

 

 

Demo步骤解析:

1.一开始选定数组的最后一个元素5作为基准值,也就是最终排序结果应该是以5为界限划分为左右两边。

2.从左边开始,寻找比5大的值,然后与5进行调换(因为如果比5小的值本来就应该排在5前面,比5大的值调换之后就去到了5的后面),一路过来找到了7,将7与5调换,结束此次遍历。

3.从右边开始,由于7已经是上一轮排好序的便不再动它,从10开始,一路向左遍历,寻找比5小的值,然后与5进行调换(因为如果比5大的值本来就应该排在5后面,比5小的值调换之后就去到了5的后前面),一路过来找到了4,将4与5调换,结束此次遍历。

4.从左边开始,由于3和4都是前两轮已经排好序的便不再动它,从2开始,一路向右遍历,寻找比5大的值,然后与5进行调换(道理同步骤2),一路过来找到了9,将9与5调换,结束此次遍历。

5.从右边开始,由于排在9后面的那几个数字都是上几轮排好序的便不再动它,从1开始,一路向右遍历,寻找比5小的值,然后与5进行调换(道理同步骤3),一下子就找到了1,将1与5调换,结束此次遍历。

6.这个时候,发现5的左右两边都是排好序了的,所以结束此轮排序,5的左右两边抽出来各自进行下一轮的排序,规则同上,直到无法再拆分下去,即完成了整体的快速排序。

    /**
     * 快速排序
     *
     * @param arr
     * @param low
     * @param hight
     * @return
     */
    public static void quickSort(int[] arr, int low, int hight) {
        int pivot, pos, t;
        if (low < hight) {
            pos = low;
            pivot = arr[pos];
            for (int i = low + 1; i < hight; i++) {
                if (pivot > arr[i]) {
                    t = arr[pos];
                    arr[pos] = arr[i];
                    arr[i] = arr[pos + 1];
                    arr[pos + 1] = t;
                    pos++;
                }
            }
            quickSort(arr,low,pos);
            quickSort(arr,pos+1,hight);
        }
    }

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值