八大排序相对应链接
目录
基本思想
归并排序就是递归得将原始数组递归对半分隔,直到不能再分(只剩下一个元素)后,开始从最小的数组向上归并排序。
- 将一个数组拆分为两个,从中间点拆开,通过递归操作来实现一层一层拆分。
- 从左右数组中选择小的元素放入到临时空间,并移动下标到下一位置。
- 重复步骤2直到某一下标达到尾部。
- 将另一序列剩下的所有元素依次放入临时空间。
- 将临时空间的数据依次放入原数据数组。
图解
动态图
流程分析
分:
分解的时候我们可以使用递归的方式进行
首先我们可以先定义三个变量,
数组的头部位置可以定义为 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是考虑到当把临时数据放到原数组的右边的那一半 } } }