八大排序之归并排序(非常重要)

 八大排序相对应链接

冒泡排序零基础

选择排序零基础

插入排序零基础

希尔排序零基础

快速排序零基础

归并排序零基础

基数排序零基础

堆排序零基础

目录

基本思想

图解

流程分析

分:

合并:

 代码


基本思想

归并排序就是递归得将原始数组递归对半分隔,直到不能再分(只剩下一个元素)后,开始从最小的数组向上归并排序。

  1. 将一个数组拆分为两个,从中间点拆开,通过递归操作来实现一层一层拆分。
  2. 从左右数组中选择小的元素放入到临时空间,并移动下标到下一位置。
  3. 重复步骤2直到某一下标达到尾部。
  4. 将另一序列剩下的所有元素依次放入临时空间。
  5. 将临时空间的数据依次放入原数据数组。

图解

动态图

 

流程分析

分:

分解的时候我们可以使用递归的方式进行

首先我们可以先定义三个变量,

数组的头部位置可以定义为 low,数组的尾部可以定义为high

因为每次分解都是要折半,所以我们可以定义数组的中间是 mid,如下图所示

我们从上图当中可以看到,我们每一次递归,都是将原来的mid当成新的high,一直到low = high的时候我们就已经可以说明我们将一个数据分离了出来。所以我们可以写以下代码来表示分。

 首先我们可以先递归左边,直到我们讲第一个值分离出去,然后再回溯,分离他右边的那个,如图所示

合并:

当递归完成之后我们该开始合并了

首先我们需要先弄懂一个地方就是合并是在哪里开始的。

首先我们要知道我们第一次回溯之后,将第二个元素分离了出来,第二个元素分离完成之后,也会回溯回去,那么此一次合并就是 值 6 和 5的合并。

下边我们为了演示选择了 5,6 , 1 , 3的合并过程

下边我们来一步一步的展示整个合并的过程,

首先我么可以定义两个指针,s1和s2,然后在定义一个新的临时数组来存储数据

 我们将指针s1的范围锁定在 s1<=min ,将指针s2的范围锁定在s2<=high,我们可以比较s1和s2当前指向的值的大小,将小的一方放入到临时数组当中去,直到s1或s2一方指向为空,那么就可以将另一方全部放入到临时数组当中去。然后将临时的代码在放回数组

代码如下:

 代码

import java.util.Arrays;

public class MergeSort {

    public static void main(String[] args) {
        int[] arr = new int[]{1,5,8,3,7,6,4,3,1651};

        sort(arr,0,arr.length-1);
        System.out.println(Arrays.toString(arr));
    }

    public static void sort(int[] arr,int left,int right){
        if(left == right){首先判断 low 和 high是否指向一个地方
            return;
        }
        int mid = (left + right ) / 2;
        sort(arr,left,mid);先递归左边
        sort(arr,mid+1,right);在递归右边
        merge(arr,left,mid,right);
    }

    public static void merge(int[] arr,int left,int mid,int right){
        int s1 = left;  //定义第一段的开始
        int s2 = mid+1;//定义第二段的开始

        int[] temp = new int[right-left +1];  //定义临时数组
        int index = 0;   //定义临时数组下标
        while (s1<=mid && s2 <=right){  //判断大小  然后将数放入临时数组
            if(arr[s1] <= arr[s2]){
                temp[index] = arr[s1];
                index++;
                s1++;
            }else {
                temp[index] = arr[s2];
                index++;
                s2++;
            }
        }

        //看看s1数组当中是不是还有数据
        while (s1<=mid){ //因为上面的循环写着 如果把数据放到数据中了 那么s1++ 所以当s1<=mid的时候 就说明左边还有数据
            temp[index] = arr[s1];
            index++;
            s1++;
        }

        while (s2<=right){
            temp[index] = arr[s2];
            index++;
            s2++;
        }

        //将临时数组当中的数据放回
        for(int j = 0;j<temp.length;j++){
            arr[j+left] = temp[j];  //j+left是考虑到当把临时数据放到原数组的右边的那一半
        }
    }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值