Merge sort java (with super detailed graphic explanation)

content

Introduction to merge sort:

Merge sort diagram:

Diagram 1

Diagram 2

Merge sort detailed steps:

1. Combination

2. Grouping

full code



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

Guess you like

Origin blog.csdn.net/Javascript_tsj/article/details/123562329