算法排序5——归并排序&分治思想

简介: 算法排序5——归并排序&分治思想

🟡前言


今天是21天挑战赛第二周,本文主要讲归并排序,也是分治思想的重要体现


🟡概述


1️⃣原理图


fbd46989ec404b9b8248f80b20b06d9a.png


2️⃣排序原理&思想体现


归并排序就是将数组尽可能拆成等分的两组,直至变成单个元素(

然后对拆分出来的元素两两排序后组合,变成一个有序的数组(


🟡调用API解决


1️⃣成员变量


private static Comparable[] assist:完成归并操作所需要的辅助数组


2️⃣构造方法和成员方法


构造方法


Merge();


成员方法


  • public static void sort(Comparable[]a):对数组a中元素进行排序
  • public static void sort(Comparable[]a, int lo, int hi):对数组a中从索引lo到索引hi之间元素进行排序
  • public static void merge(Comparable[]a, int lo, int mid,int hi):数组a中从从索引 lo 到索引 min 为一个子数组,从索引 min+1 到索引 hi 为另一个子数组,把a中的两个子数组合并成一个大数组
  • public static boolean less(Comparable x, Comparable y):判断x是否小于y
  • public static void exch(Comparable[]a, int i, int j):交换数组a中下标为 i 和 j 的元素


3️⃣解题思路


1.定义并初始化一个辅助数组,来完成归并操作

2.定义并初始化数组的最小索引 lo最大索引 hi

3.调用一个方法对数组内元素进行排序后归并排序


4️⃣归并排序思路


1.定义三个"指针"p1、p2和 i,用来指向第一子数组的元素、第二子数组的元素和辅助数组的元素

2.比较p1和p2指向元素的大小,将较小的放入辅助数组中


26321235ae084d4e9191ccd05bb8376f.jpg


3.将刚才较小元素的索引值和辅助数组索引值都加1,

4.将指针指向新的元素值与另一个子数组内指针指向元素比较,并将较小的元素存放到辅助数组内

5.重复2-4的步骤,直至其中一个指针指向该子数组的最后一个元素为止


7d3efdcf41c24a4b814f6f2c6b7ecf95.png

579dfd4ad8fc43acb82d3a94a2361e1a.png

bac3a5d4167641d3a3cc4730552d3f53.png

3eb718997e3c4184ac135044a76b081c.png

d29713b098154e2fad01af01aa1b7046.png


6.当其中一个指针走完时,直接将另一个子数组中元素放入辅助数组中


4eda14f1aaf7457ca4e4837cca814f72.png


7.将排序完成的元素放回元素组中


362b816205614ca4842746e57f79f7b0.png


5️⃣归并排序代码实现


//定义一个归并排序的含参方法
public static void merge(Comparable[]a, int lo, int mid,int hi){
        int p1 = lo;//定义并初始化一个子数组的索引
        int p2 = mid + 1;//定义并初始化另一个子数组的索引
        int i = lo;//定义并初始化辅助数组的索引
        //当两个索引值都在索引范围内,将数值更小的元素放入辅助数组
        while (p1 <= mid && p2 <= hi){
            if(less(a[p1],a[p2])){
                assist[i++] = a[p1++];
            }
            else {
                assist[i++] = a[p2++];
            }
        }
        //当p2索引值超出索引范围时(即满足p1没有超出索引范围)
        while (p1 <= mid){
            assist[i++] = a[p1++];//将p1索引所对应剩下的元素复制到辅助数组中
        }
        //当p1索引值超出索引范围时(即满足p2没有超出索引范围)
        while (p2 <= hi){
            assist[i++] = a[p2++];//将p2索引所对应剩下的元素复制到辅助数组中
        }
        //将已排序的辅助数组赋值给原数组
        for(int index = lo; index <= hi; index++){
            a[index] = assist[index];
        }
    }


6️⃣完整代码


public class MergeSort {
    private static  Comparable[] assist;
    public static void sort(Comparable[] a){
        assist = new Comparable[a.length];
        int lo = 0;
        int hi = a.length-1;
        sort(a,lo,hi);//归并排序
    }
    public static void sort(Comparable[]a, int lo, int hi){
        if(hi <= lo){
            return;
        }
        int mid = lo + (hi-lo)/2;
        sort(a, lo, mid);//子数组排序
        sort(a, mid+1, hi);//子数组排序
        merge(a, lo, mid, hi);//合成有序的一个大数组
    }
    public static void merge(Comparable[]a, int lo, int mid,int hi){
        int p1 = lo;//定义并初始化一个子数组的索引
        int p2 = mid + 1;//定义并初始化另一个子数组的索引
        int i = lo;//定义并初始化辅助数组的索引
        //当两个索引值都在索引范围内,将数值更小的元素放入辅助数组
        while (p1 <= mid && p2 <= hi){
            if(less(a[p1],a[p2])){
                assist[i++] = a[p1++];
            }
            else {
                assist[i++] = a[p2++];
            }
        }
        //当p2索引值超出索引范围时(即满足p1没有超出索引范围)
        while (p1 <= mid){
            assist[i++] = a[p1++];//将p1索引所对应剩下的元素复制到辅助数组中
        }
        //当p1索引值超出索引范围时(即满足p2没有超出索引范围)
        while (p2 <= hi){
            assist[i++] = a[p2++];//将p2索引所对应剩下的元素复制到辅助数组中
        }
        //将已排序的辅助数组赋值给原数组
        for(int index = lo; index <= hi; index++){
            a[index] = assist[index];
        }
    }
    public static boolean less(Comparable x, Comparable y){
        return x.compareTo(y) < 0;
    }
}


🟡空间复杂度


  • 总共分为log8(底数为2)层,即log2(n)


  • 每一层都有2^k个元素(8,4,2)


  • 每个子数组的长度:2^(3-k)(0,2,4)


  • 归并最多需要次数:2^(3-k)


  • 每层归并需要的次数:每一层元素个数*每个子数组的长度:23 =8


  • 总次数:层数 * 每层归并需要的次数:3 * 23 ,即log2(n) * 2log2(n) = log2(n) * n


  • 所以时间复杂度为:O(nlogn)


🟡归并排序缺点


要开辟一个新空间,使得空间复杂度提高,典型的 以时间换空间


🟡结语


归并排序利用了分治思想和递归的思路,所以要先掌握这两个知识点才能掌握这种算法

相关文章
|
30天前
|
算法 调度
【软件设计师备考 专题 】算法探索:排序、查找、数值计算和字符串处理(二)
【软件设计师备考 专题 】算法探索:排序、查找、数值计算和字符串处理
32 0
|
16天前
|
存储 算法 搜索推荐
【数据结构与算法】归并排序(详解:递归与非递归的归并排序 | 赠:冒泡排序和选择排序)
【数据结构与算法】归并排序(详解:递归与非递归的归并排序 | 赠:冒泡排序和选择排序)
|
25天前
|
存储 搜索推荐 算法
【数据结构】八大排序之计数排序算法
【数据结构】八大排序之计数排序算法
11 4
|
25天前
|
搜索推荐 算法
【数据结构】八大排序之归并排序算法
【数据结构】八大排序之归并排序算法
20 5
|
25天前
|
搜索推荐 算法 编译器
【数据结构】八大排序之快速排序算法
【数据结构】八大排序之快速排序算法
35 4
|
27天前
|
算法 Python
数据结构与算法 经典排序方法(Python)
数据结构与算法 经典排序方法(Python)
24 0
|
28天前
|
存储 算法 搜索推荐
【算法】七大经典排序(插入,选择,冒泡,希尔,堆,快速,归并)(含可视化算法动图,清晰易懂,零基础入门)
【算法】七大经典排序(插入,选择,冒泡,希尔,堆,快速,归并)(含可视化算法动图,清晰易懂,零基础入门)
|
30天前
|
存储 算法
【软件设计师备考 专题 】算法探索:排序、查找、数值计算和字符串处理(三)
【软件设计师备考 专题 】算法探索:排序、查找、数值计算和字符串处理
27 0
|
30天前
|
存储 算法 搜索推荐
【软件设计师备考 专题 】算法探索:排序、查找、数值计算和字符串处理(一)
【软件设计师备考 专题 】算法探索:排序、查找、数值计算和字符串处理
108 0
|
存储 机器学习/深度学习 人工智能
【排序算法】数据结构排序详解
【排序算法】数据结构排序详解