排序2-时间复杂度为O(nlogn)的算法 归并排序 快排

本文深入探讨两种时间复杂度为O(nlogn)的经典排序算法——归并排序和快排。归并排序采用分治策略,通过递归分解和合并有序子序列实现排序。快排则通过选取枢轴元素进行分区操作,实现原地排序。文章分析了两种算法的性能、稳定性、时间复杂度和空间复杂度,并对比了它们的差异。同时,还讨论了在面试中常考的TopK问题的解决方案。
摘要由CSDN通过智能技术生成

上一篇博文排序1主要讲的是关于评定算法性能的一些指标,以及时间复杂为O(n2)的排序算法。这一篇博文我重点讲述世家复杂度为O(nlogn)的两个经典算法—归并排序 和快排
关于这两个算法 网上的资料很多 在面试中也会经常会被问到(特别是快排),这里我结合自己的理解和总结,写的不好的地方 请多指教。

归并排序(MergeSort)

归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。
归并排序的核心思想:如果要排序一个数组,我们先把数组从中间分成前后两部分,然后对前后两部分分别排序,再将排好序的两部分合并在一起,这样整个数组就都有序了。
在这里插入图片描述
我们可以看到归并排序的数据用书的结构来表示后,分和治都是一颗满二叉树,高度为O(log2n)。

分:采用递归的方法进行分解。

将待排序数组中的n个数据分解为n个有序的子数组,采用递归的方法。
首先,我们写出其递推公式及其终止条件:

递推公式:merge_sort(p…r) = merge(merge_sort(p...q),merger_sort(q+1,...r))
终止条件:p>=r

由递推公式写出"分"的代码:

public static void merge_sort(int[] a,int p,int r){
        //递归终止条件
        if(p>=r) return;
        //取p到r之间的中间位置q
        int q=(p+r)/2;
        //分治递归
        merge_sort(a,p,q);
        merge_sort(a,q+1,r);

        //将a[p,...,q]和a[q+1,..,r]合并为a[p,..,r]
        merge(a,p,q,r);
    }
治:合并相邻有序子序列

再来看看治阶段,我们需要将两个已经有序的子序列合并成一个有序序列,比如上图中的最后一次合并,要将[4,5,7,8]和[1,2,3,6]两个已经有序的子序列,合并为最终序列[1,2,3,4,5,6,7,8],来看下实现步骤。
  在这里插入图片描述
在归并排序中最耗时的就是治(将两个小数组合并为大数组的过程)
治的java代码:

private static void merge(int[] arr,int left,int mid,int right){
        int i = left;//左序列指针
        int j = mid+1;//右序列指针
        int t = 0;//临时数组指针
        int[] temp=new int[right-left+1];    //申请一个大小和a[left,..,right]一样大的数组
        while (i<=mid && j<=right){
            if(arr[i]<=arr[j]){
                temp[t++] = arr[i++];
            }else {
                temp[t++] = arr[j++];
            }
        }
        while(i<=mid){//将左边剩余元素填充进temp中
            temp[t++] = arr[i++];
        }
        while(j<=right){//将右序列剩余元素填充进temp中
            temp[t++] = arr[j++];
        }
        t = 0;
        //将temp中的元素全部拷贝到原数组中
        while(left <= right){
            arr[left++] = temp[t++];
        }
    }
归并排序的完整代码
package SortAlgorithm;

/**
 * 归并排序(体现分治的思想 利用到递归)
 * 归并排序是一个稳定的算法(值相同的元素,再合并前后的先后顺序不变)
 归并排序的时间复杂度是O(nlogn),这里值得注意的是,归并排序的执行效率和要排序的原始数组的有序程度无关,所以其时间复杂度是非常稳定的,不顾那是最好情况,最坏情况,还是平均情况,时间复杂度都是O(nlogn)
 归并排序的空间复杂度是O(n),归并排序是非原地排序算法
 * @author xjh 2018.10.22
 */
public class Sort02ToMergeSort {
    public static void main(String[] args) {
        int[] a={12,2,3,10,4,8,13,3};
        int n=a.length;
        mergeSort(a,n);
        for(int i=0;i<n;i++){
            System.out.print(a[i]+" ");
        }
        System.out.println();
    }

    /**
     * 归并排序
     * @param a
     * @param n
     */
    public static void mergeSort(int[] a,int n){
        merge_sort(a,0,n-1);
    }
    public static void merge_sort(int[] a,int p,int r){
        //递归终止条件
        if(p>=r) return;
        //取p到r之间的中间位置q
        int q=(p+r)/2;
        //分治递归
        merge_sort(a,p,q);
        merge_sort(a,q+1,r);

        //将a
时间复杂度为O(nlogn)的排序算法有希尔排序,堆排序,快速排序归并排序。其中归并排序是一种稳定的排序算法,而希尔排序、堆排序和快速排序是不稳定的排序算法。 <span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [python-归并排序算法.docx](https://download.csdn.net/download/qq_43934844/87893705)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [时间复杂度O(nlogn)的排序算法](https://blog.csdn.net/qq_43533956/article/details/123978524)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [时间复杂度为O(nlogn)的排序算法](https://blog.csdn.net/qq_46130027/article/details/129765856)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值