首先上图:
下面这个图就是,一开始分成了左右两部分,左边是4578,右边是1236,然后分别拿左右两部分的第一个数字进行比较,发现右边的的1小于左边的4,然后右边部分指针右移一个单位,变成了2去和左边的4比较大小,这样以此类推…
0:我们一开始将左边的第一个数字用i来指向,右边第一个数字用j来指向,那么我们可以一开始定义一个方法
/**
* @arr 排序的原始数组
* @param left 左边有序序列的初始索引
* @param mid 中间索引
* @param right 右边索引
* @param temp 做中转的数组
*/
public static void merge(int[] arr,int left, int mid, int right,int[] temp){
int i = left; // 初始化i,左边这个有序序列的初始索引
int j = mid +1; //初始化j,右边这个有序序列的初始索引
int t = 0; // 指向temp数组的当前索引
1:然后我们进入到了第一个循环
先把左右两边(有序)的数据按照规则填充到temp数组中,知道左右两边的有序序列有一边处理完毕为止
(1)i和j分别代表左右两部分的第一个数字,然后用他两作比较,将小的那个数字现存放到临时数组temp中,然后temp和较小的左边部分指针都要加一**
while (i<= mid && j<=right){ //继续
// 如果左边的有序序列的当前元素,小于等于右边有序序列的当前元素
// 即将左边的当前元素,拷贝到temp数组
// 然后t要往后移动一下
if (arr[i] <= arr[j]){
temp[t] = arr[i];
t+=1;
i+=1;
}
}
(2)如果是右边的小就是这个情况,使用else
while (i<= mid && j<=right){ //继续
// 如果左边的有序序列的当前元素,小于等于右边有序序列的当前元素
// 即将左边的当前元素,填充到temp数组
// 然后t要往后移动一下
if (arr[i] <= arr[j]){
temp[t] = arr[i];
t+=1;
i+=1;
}else { //反之,将右边有序序列的当前元素填充到temp数组
temp[t] = arr[j];
t+=1;
j+=1;
}
}
2:我们进入第二大步骤,按照我们的图片所示,我们会出现两个情况就是当右边已经全部填入temp但是左边还留有数字或者左边全部填入temp但是右边还有数字的时候:我们需要做一个循环:
//把有剩余数据的一边的数据依次全部填充到temp去
while (i <= mid){ //左边的有序序列还有剩余的元素,就全部填充到temp中
temp[t] = arr[i];
t+=1;
i+=1;
}
while (j <= right){ //右边的有序序列还有剩余的元素,就全部填充到temp中
temp[t] = arr[j];
t+=1;
j+=1;
}
3:进入第三大步骤,也就是我们的拷贝过程,我们要将得到的temp数字拷贝到原来的数组中去,但是这个拷贝不是一下子就把八个数字全部拷贝进去的,他有一个过程,
首先是我们定义一个新的指针tempLeft,然后初始为0,right是1,然后第二次合并tempLeft变成了2,right变成了3,然后再整体合并一下,tempLeft变成了0,right变成了3,同理,右边也是这样,最后tempLeft成了0right成了7就把全部的数字拷贝进去了。(相当于:01->23-> 03-> 45-> 67-> 47-> 07)
//(三)
//将temp数组中的元素拷贝到arr
// 并不是每一次都拷贝所有
t = 0;
int tempLeft = left;
//第一次合并时 tempLeft=0,right = 1 // tempLeft = 2 right = 3 // tempLeft = 0 right = 3
// 最后一次 tempLeft = 0 right = 7
while (tempLeft <= right){
arr[tempLeft] = temp[t];
t +=1;
tempLeft+=1;
}
4:第四大步:我们前面这几步相当于一直是从已经分解好了那个时候开始的,所以我们需要使用递归调用将原数组分解:
//分加和的方法
public static void mergeSort(int[] arr, int left,int right,int[] temp){
if (left<right){
int mid = (left+right)/2; //中间索引
// 向左递归进行分解
mergeSort(arr,left,mid,temp);
//向右递归分解
mergeSort(arr,mid+1,right,temp);
}
}
5:第五步:编写主方法,主方法中定义初始数组和临时数组,调用方法
public class MergetSort {
public static void main(String[] args) {
int arr[] = {8,4,5,7,1,3,6,2};
int temp[] = new int[arr.length]; // 归并排序需要一个额外空间
mergeSort(arr,0, arr.length-1,temp);
System.out.println("归并排序后="+ Arrays.toString(arr));
}
最后需要再递归分解的时候加入合并:
//分加和的方法
public static void mergeSort(int[] arr, int left,int right,int[] temp){
if (left<right){
int mid = (left+right)/2; //中间索引
// 向左递归进行分解
mergeSort(arr,left,mid,temp);
//向右递归分解
mergeSort(arr,mid+1,right,temp);
//合并
merge(arr,left,mid,right,temp);
}
}
全部代码:
package 二分法排序;
import java.util.Arrays;
/**
* @author ${范涛之}
* @Description
* @create 2021-11-04 0:13
*/
public class MergetSort {
public static void main(String[] args) {
int arr[] = {8,4,5,7,1,3,6,2};
int temp[] = new int[arr.length]; // 归并排序需要一个额外空间
mergeSort(arr,0, arr.length-1,temp);
System.out.println("归并排序后="+ Arrays.toString(arr));
}
//分加和的方法
public static void mergeSort(int[] arr, int left,int right,int[] temp){
if (left<right){
int mid = (left+right)/2; //中间索引
// 向左递归进行分解
mergeSort(arr,left,mid,temp);
//向右递归分解
mergeSort(arr,mid+1,right,temp);
//合并
merge(arr,left,mid,right,temp);
}
}
// 首先写合并的方法
// 需要四个参数,原数组,左指针,右指针,中间值,还有一个临时数组temp
/**
* @arr 排序的原始数组
* @param left 左边有序序列的初始索引
* @param mid 中间索引
* @param right 右边索引
* @param temp 做中转的数组
*/
public static void merge(int[] arr,int left, int mid, int right,int[] temp){
System.out.println("xxx");
int i = left; // 初始化i,左边这个有序序列的初始索引
int j = mid +1; //初始化j,右边这个有序序列的初始索引
int t = 0; // 指向temp数组的当前索引
// (一)
//先把左右两边(有序)的数据按照规则填充到temp数组中,知道左右两边的有序序列有一边处理完毕为止
while (i<= mid && j<=right){ //继续
// 如果左边的有序序列的当前元素,小于等于右边有序序列的当前元素
// 即将左边的当前元素,填充到temp数组
// 然后t要往后移动一下
if (arr[i] <= arr[j]){
temp[t] = arr[i];
t+=1;
i+=1;
}else { //反之,将右边有序序列的当前元素填充到temp数组
temp[t] = arr[j];
t+=1;
j+=1;
}
}
// (二)
//把有剩余数据的一边的数据依次全部填充到temp去
while (i <= mid){ //左边的有序序列还有剩余的元素,就全部填充到temp中
temp[t] = arr[i];
t+=1;
i+=1;
}
while (j <= right){ //右边的有序序列还有剩余的元素,就全部填充到temp中
temp[t] = arr[j];
t+=1;
j+=1;
}
//(三)
//将temp数组中的元素拷贝到arr
// 并不是每一次都拷贝所有
t = 0;
int tempLeft = left;
//第一次合并时 tempLeft=0,right = 1 // tempLeft = 2 right = 3 // tempLeft = 0 right = 3
// 最后一次 tempLeft = 0 right = 7
System.out.println("tempLeft="+tempLeft+" right="+right);
while (tempLeft <= right){
arr[tempLeft] = temp[t];
t +=1;
tempLeft+=1;
}
}
}
运行结果:
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/81074.html