1, Concept
Merge Sort is an effective and stable sorting algorithm based on merge operation. This algorithm is a very typical application of divide and conquer method.
The ordered subsequences are combined to obtain a completely ordered sequence; That is, each subsequence is ordered first, and then the subsequence segments are ordered.
2, Sorting process
1. Merge operation refers to the method of merging two sequential sequences into one sequential sequence.
For example: array {6202100301, 38, 8, 1}
Initial state: 6202100301,38,8,1
After the first merger: {6202}, {100301}, {8,38}, {1};
After the second merger: {6100202301}, {1,8,38};
After the third merger: {1,6,8,38100202301};
2. The merging operation steps are as follows:
(1) The application space is the sum of two ordered sequences. This space is used as an auxiliary array
(2) Set two pointers. The initial position is the starting position of the two sorted sequences
(3) Compare the elements pointed to by the two pointers, select the relatively small element, put it into the merge space (select the left group equally), and move the pointer to the next position.
Repeat step 3 until a pointer is out of bounds. Copy all the remaining elements of another sequence directly to the end of the merge sequence (auxiliary array), and copy the auxiliary array data back to the original array.
3, Estimation of time complexity by Master formula
Master formula: analyze the time complexity of recursive functions and require the same scale of subproblems
The shape is as follows:
For the recursive function of T(N) = a * T(N/b) + O(N^d) (where a, B and d are constants), the time complexity can be determined directly through the Master formula
1) If log (B, a) < D, the time complexity is O(N^d)
2) If log (B, a) > D, the time complexity is O(N^log(b,a))
3) If log(b,a) == d, the time complexity is O(N^d * logN)
According to Master formula, T(N) =2 * T(N/2) + O(N)
Because each time it is divided into two subproblems, each subproblem accounts for half of the total scale, and the time complexity of the merging process is O(N)
The time complexity of merging sorting is O(N*logN).
4, Code implementation
1. Recursive method implementation
/** * 1.Recursive method implementation */ public static void mergeSort1(int[] arr) { if (arr == null || arr.length < 2) { return; } process(arr, 0, arr.length - 1); } private static void process(int[] arr, int l, int r) { if (l == r) { return; } int mid = l + ((r - l) >> 1); // Left group recursion process(arr, l, mid); // Right group recursion process(arr, mid + 1, r); // merge merge(arr, l, mid, r); } private static void merge(int[] arr, int l, int m, int r) { // Auxiliary array int[] help = new int[r - l + 1]; int i = 0; // Left group position int pL = l; // Right group position int pR = m + 1; while (pL <= m && pR <= r) { // Who small copy who, equal copy left group help[i++] = arr[pL] <= arr[pR] ? arr[pL++] : arr[pR++]; } // Only one of pL and pR will cross the boundary, that is, only one of the following two while will execute while (pL <= m) { help[i++] = arr[pL++]; } while (pR <= r) { help[i++] = arr[pR++]; } // Copy back to the original array for (int j = 0; j < help.length; j++) { arr[l + j] = help[j]; } }
2. Iterative implementation
Define a step size with an initial value of 1. Starting from the number at position 0, the number of every two steps is copied back to the original array after the merge, step * 2; Starting from the number at position 0, copy the number of steps every two steps back to the original array after merging, step * 2... Until (step > array len gt h / 2)
/** * 2.Merge and sort by iteration * <p> * The complexity of step adjustment times is logN. Each step adjustment will traverse the entire array. The complexity is N and the time complexity is O(N*logN) */ public static void mergeSort2(int[] arr) { if (arr == null || arr.length < 2) { return; } int N = arr.length; // Step initial value int mergeSize = 1; // Step length cannot exceed array length while (mergeSize < N) { // The first position of the current left group int L = 0; // The left group cannot exceed the length of the array while (L < N) { // Last position of left group int M = L + mergeSize - 1; // If the last position of the left group is out of bounds, it indicates that the left group is not enough, so merge is not required if (M >= N) { break; } // Last position of the right group // The first position of the right group is m + 1. If the number requirements are met, the size of the right group is mergeSize, so the last position is (M + 1) + mergeSize - 1 // If not, the maximum position of the array is N - 1 int R = Math.min(M + mergeSize, N - 1); // At present, left group: L......M, right group: M+1......R merge(arr, L, M, R); // The position of the next left group (so it is necessary to judge l < n) L = R + 1; } // Prevent overflow // When the step size is very close to the maximum value of N, multiply by 2 to expand the step size, and the step size overflows // Cannot take > =. If the maximum value is 9, the step size will not be expanded when mergeSize = 4, but there is another merge when mergeSize = 8, so it cannot be taken= if (mergeSize > N / 2) { break; } // The step size is expanded twice each time mergeSize <<= 1; } }