分治思想—归并和快速排序

常规唠嗑
  • 算法的稳定性和正确性:有时候排序算法会涉及到稳定性,首先稳定性是在算法具备正确性的前提下,对于元素的位置是否发生变更的一个说法。假如一个算法运算结束,在最终的序列里,保持两个元素之间初始位置不变,则属于稳定。
  • 有木有以前看过《啊哈,算法》的小伙伴,来来来,交流交流思想
归并
  • 思路: 1,归并老被叫做二路归并,为什么是二路,不是一路,三路?就是说啊,这个算法,每次都有两条线去排序。 2,什么叫做归并?我不管你几路,最终我需要一个结果,所以,各路人马必须并拢。
  • 重点:2条路同时排序;合并这两条路;先逐步分解一路,合并时,通过对参数的调用(分解第二路)
  • 意会路线图:天下分久必合合久必分,二路归并完整提现。假设原始序列有5个小国元素,我现在要排出强弱顺序,你不能让我1号国家一个一个去打吧,一个一个打搞车轮战术么?而且这种拉风的排行榜,当然是越快越好。 所以,先划分组,组再划分组,然后排出强弱,最终合并。
  • 解题注意点:1,分合同步:未排序的可以分,合的只能是有序子集;2,合并时注意子集大小判分之后的剩余元素;3,开辟新空间接收合并集;
二路代码 —思想核心
    public static int[] sort(int[] sourceArray) {
        int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);
        //只有一个元素
        if (arr.length < 2) {
            return arr;
        }
        // 取出将整体划分为 2 路的中间节点
        int middle = (int) Math.floor(arr.length / 2);

		// 递归划分子集—逐步裂变
        int[] left = sort(Arrays.copyOfRange(arr, 0, middle));
        int[] right = sort(Arrays.copyOfRange(arr, middle, arr.length));
		// 合并,通过改变递归数组的长度,逐步收拢子集
        return merge(left,right);
    }
归并代码
 public static int[] merge(int[] left, int[] right) {
        int[] result = new int[left.length + right.length];
        int i = 0;
        // 归并已排序两个子集
        while (left.length > 0 && right.length > 0) {
            if (left[0] <= right[0]) {
                result[i++] = left[0];
                left = Arrays.copyOfRange(left, 1, left.length);
            } else {
                result[i++] = right[0];
                right = Arrays.copyOfRange(right, 1, right.length);
            }
        }
		// 假如两个数组大小比对排序合并之后,left数组还存有剩余比之前元素大的,直接将剩余元素添加到合并集
        while (left.length > 0) {
            result[i++] = left[0];
            left = Arrays.copyOfRange(left, 1, left.length);
        }
		// 假如两个数组大小比对排序合并之后,right数组还存有剩余比之前元素大的,直接将剩余元素添加到合并集
        while (right.length > 0) {
            result[i++] = right[0];
            right = Arrays.copyOfRange(right, 1, right.length);
        }

        return result;
    }
快速排序
  • 思路:归并之所以快,是因为多路同时搞;快速排序为什么快速?我没有多条路走,但我可以一条路A—>B,也可以B—>A呀。我两头同时开搞,就不像冒泡,插入之类的,我只能是A—>B . 在通信传输里边,这好像是单工吧。优化通信信道时,会说将单工,变成半双工或者全双工。我理解,快速排序,就是单工—>双工的优化。
  • 意会路线图:因为是左右两头同时开搞,所以,需要一个规则,左边亲们搞啥,右边亲们搞啥。因为是排序的大前提,所以是:选定一个基数,左边搞比基数大的,右边搞比基数小的。然后,先有个大致范围:即一趟下来能根据既定基数获取所有比之较大或者较小的子集。PS:哪边搞大哪边搞小,其实都阔以,看升序或者是降序。然后在各自子集里,重复相同步骤。
  • 重点:需要基数、子集再排序(递归)
  • 关键点:原数组中子集的临界点维护;未开辟新空间,注意原始数组的维护
代码
  public static int[] quickSort(int[] arr,int l,int r){

        // 确定一次运算的基准值
        int base = arr[l];
        int lindex = l,rindex=r;
        while (lindex<rindex){
            // 从右至左找到第一个小于基准值的位置
            while (arr[rindex]>base && lindex<rindex){
                rindex--;
            }
            // 从左至右找到第一个大于基准值的位置
            while (arr[lindex]<base && lindex<rindex ){
                lindex++;
            }

            // 处于中间位置,一轮运算暂未结束,进行交换
            if(lindex<rindex && arr[lindex]!=arr[rindex]){
                int temp = arr[rindex];
                arr[rindex]=arr[lindex];
                arr[lindex]=temp;
            }
            //向右移动左值指针,或者向左移动右指针都阔以
            if(lindex<rindex && arr[lindex]==arr[rindex]){
                lindex++;
            }
        }

        // 分治前一轮的再排序
        if(l<lindex-1){
            arr = quickSort(arr,l,lindex-1);
        }
        if(rindex+1<r){
            arr = quickSort(arr,rindex+1,r);
        }

        return arr;
    }
一点不成熟的想法
  • 快排和归并在分治的思想下,有着异曲同工之妙。都会划分子集,不同的地方在于,子集的划分规则以及被划分子集的特点,另外是否有新空间的申请。
  • 我当年应该是被吓傻了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值