content
Introduction to merge sort :
Merge sort (MERGE-SORT) is a sorting method implemented by the idea of merging. The algorithm adopts the classic divide-and-conquer strategy (divide-and-conquer method divides the problem into small problems and then solves them recursively. , and the conquer stage "fixes" the answers obtained in the division stage together, that is, divide and conquer).
Merge sort diagram:
Diagram 1
Schematic diagram of merge sort idea 1 - basic idea:
Diagram 2
Schematic diagram
of the idea of merge sort Combine the two already ordered subsequences [4,5,7,8] and [1,2,3,6] into the final sequence [1,2,3,4,5,6,7,8] , look at the implementation steps:
Merge sort detailed steps:
Application example of merge sort:
give you an array, arr= Array(8, 4, 5, 7, 1, 3, 6, 2), please use merge sort to complete the sorting.
To make it easier for you to understand, I have separated the steps:
Write the hardest combination first
1. Combination
1. Let's write the code of the black box first, that is, the array has become (4, 5, 7, 8, 1, 2, 3, 6) How do we synthesize it 1 2 3 4 5 6 7 8
You can take a look at diagram 2
package suanfa;
import java.util.Arrays;
import java.util.Scanner;
public class xishuarr {
public static void main(String[] args) {
int arr[]= {8,4,5,7,1,3,6,2};
//假设已经到最后一步
int arrys[]= {4 ,5 ,7 ,8,1 ,2, 3, 6};
int[] add=new int[8];
//第一个参数表示传入数组{4 ,5 ,7 ,8,1 ,2, 3, 6}
//第二个参数表示这个数组的第一个位置 即是0
//第三个参数表示这个数组的中间位置 (0+7)/2=3
//第四个参数 存放临时数组的
merge(arrys,0,3,7,add);
}
/**
*
* @param arr 排序的原始数组
* @param left 左边有序序列的初始索引
* @param mid 中间索引
* @param right 右边索引
* @param temp 做中转的数组
*/
//4 5 7 8 1 2 3 6
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数组
//直到左右两边的有序序列,有一边处理完毕为止
while(i<=mid&&j<=right) {
if(arr[i]<arr[j]) {
temp[t]=arr[i++];
/**
* 这里我们这里是:temp[t]=arr[i++];
* 如果不好理解,你可以写成这样:
* temp[t]=arr[i];i++;
*/
}
else {
temp[t]=arr[j++];
}
//因为无论执行if里面的语句还是else里面的语句,t都要加1,所以把t移出来.
t++;
}
//2.
//把有剩余数据的一边的的数据依次全部填充到temp
//由上述循环条件:i<=mid&&j<=right 可知
//此时要么要么j>right i>mid
while(i<=mid) {
temp[t]=arr[i];
t++;
i++;
}
while(j<=right) {
temp[t]=arr[j];
t++;
j++;
}
//3.
//把temp的数组转移到arr上
int n=0;
while(n<arr.length){
arr[n]=temp[n];
n++;
}
System.out.println(Arrays.toString(arr));
}
}
operation result:
2. Grouping
Write the code in the black box:
Going back to the beginning, how do we go from dividing the array into black boxes like this?
Use recursive thinking to divide:
method:
/**
* 分
* @param arr 排序的原始数组
* @param left 左边有序序列的初始索引
* @param right 右边索引
* @param temp 做中转的数组
*/
public static void mergeSort(int[] arr,int left,int right,int[] temp) {
//求中间索引
int mid=(left+right)/2;
if(left<right) {
//左边递归分解
mergeSort(arr,left,mid,temp);
//右边递归分解
mergeSort(arr,mid+1,right,temp);
System.out.println(" 最左边索引:"+left+"\t最右边边索引:"+right+"\t"+Arrays.toString(arr));
}
}
Main function:
public static void main(String[] args) {
int arr[]= {8,4,5,7,1,3,6,2};
//假设已经到最后一步
int arrys[]= {4 ,5 ,7 ,8,1 ,2, 3, 6};
int[] add=new int[8];
//第一个参数表示传入数组{4 ,5 ,7 ,8,1 ,2, 3, 6}
//第二个参数表示这个数组的第一个位置 即是0
//第三个参数表示这个数组的中间位置 (0+7)/2=3
//第四个参数 存放临时数组的
// merge(arrys,0,3,7,add);
mergeSort(arr,0,7,add);
}
result:
Some students may have doubts when they see the results. That is, your recursive foundation is relatively poor, don't be afraid, I will give you a detailed explanation.
If there is no problem, you can skip the following questions:
Question 1: Why does the array not change?
Because we just divide without changing the position of the array
Question 2: Why is it output 7 times?
As shown in the figure below, we divided a total of 7 times, so output 7 times
Question 3: What does the leftmost index and the rightmost index mean?
This is deliberately added to make it easier for everyone to understand the order of recursion
Left: 0 Right: 1 in the first line means: the leftmost index is: 0 and the rightmost index is: 1
Then you look at the picture below:
So the recursive order:
I believe that at this time, the students will deepen their understanding of the order of recursion
Let's, analyze, the part we've done:
We have completed the part of array division , and then → governance (combination) we are combining 2 ordered numbers with 4 into 1 ordered array.
We can take the previous rule (combination) from the original: combine 2 sorted numbers of 4 into 1 sorted array. changed to:
Combine 2 sorted numbers of n into 1 sorted array
If you don't understand, look at the picture:
This is what we put together at the beginning:
Then the difference between the following two steps and the above picture is:
Above: 2 numbers containing 4 ordered numbers form an ordered array
The next 2 images: 2 containing 2 ordered numbers form an ordered array
Therefore:
We changed the code that was only applicable in one case to a generic one
previous:
generic:
//3.
//把temp的数组转移到arr上
int n=0;
int tempLeft=left;
while(tempLeft<=right){
arr[tempLeft]=temp[n];
n++;
tempLeft++;
}
After the modification, we add the combination to the method of dividing:
In this way, it is possible to achieve one combination per minute
full code
import java.util.Arrays;
import java.util.Scanner;
public class xishuarr {
public static void main(String[] args) {
int arr[]= {8,4,5,7,1,3,6,2};
int[] add=new int[arr.length];
System.out.println("排序前:"+Arrays.toString(arr));
System.out.println("排序过程:");
mergeSort(arr,0,add.length-1,add);
System.out.println("排序后:"+Arrays.toString(arr));
}
/**
* 分
* @param arr 排序的原始数组
* @param left 左边有序序列的初始索引
* @param right 右边索引
* @param temp 做中转的数组
*/
public static void mergeSort(int[] arr,int left,int right,int[] temp) {
//求中间索引
int mid=(left+right)/2;
if(left<right) {
//左边递归分解
mergeSort(arr,left,mid,temp);
//右边递归分解
mergeSort(arr,mid+1,right,temp);
merge(arr,left,mid,right,temp);
System.out.println(" 最左边索引:"+left+"\t最右边边索引:"+right+"\t"+Arrays.toString(arr));
}
}
/**
*
* @param arr 排序的原始数组
* @param left 左边有序序列的初始索引
* @param mid 中间索引
* @param right 右边索引
* @param temp 做中转的数组
*/
//4 5 7 8 1 2 3 6
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数组
//直到左右两边的有序序列,有一边处理完毕为止
while(i<=mid&&j<=right) {
if(arr[i]<arr[j]) {
temp[t]=arr[i++];
/**
* 这里我们这里是:temp[t]=arr[i++];
* 如果不好理解,你可以写成这样:
* temp[t]=arr[i];i++;
*/
}
else {
temp[t]=arr[j++];
}
//因为无论执行if里面的语句还是else里面的语句,t都要加1,所以把t移出来.
t++;
}
//2.
//把有剩余数据的一边的的数据依次全部填充到temp
//由上述循环条件:i<=mid&&j<=right 可知
//此时要么i>mid 要么j>right
while(i<=mid) {
temp[t]=arr[i];
t++;
i++;
}
while(j<=right) {
temp[t]=arr[j];
t++;
j++;
}
//3.
//把temp的数组转移到arr上
int n=0;
int tempLeft=left;
while(tempLeft<=right){
arr[tempLeft]=temp[n];
n++;
tempLeft++;
}
}
}
result:
Welcome old irons to like and favorite