Sort Algorithm (4) -- merge sort and Recursion; merge sort algorithm and Recursion

Basic Ideas
Before analyzing the sort by merging, let's take a look**Grouping Algorithm****.**

The basic idea of the grouping algorithm is to break down a problem of N into K subproblems of small scale. These subproblems are independent of each other and are of the same nature as the original problem. You can obtain the solution of the subproblem.

General steps of the divide and conquer algorithm:

(1) decomposition: the problems to be solved are divided into several similar problems of small scale;

(2) solve the problem by using a simple method when the sub-problem is divided into sufficient hours;

(3) Merge sub-problems to form the solution of the original problem according to the requirements of the original problem.

**Merge Sorting is a typical application of grouping algorithms.**

Merging and sorting first splits an unordered N-long array into N ordered sub-sequences (only one data sequence is considered as an ordered sequence), and then merges them two by one, then, the merged sub-sequences of N/2 (or N/2 + 1) are merged in pairs, and a complete ordered array is obtained accordingly. The process is shown in:

Java Implementation
The core idea of merging and sorting is to merge two ordered arrays into another array.**Extra space required**.

The first step is to clarify the idea of merging. Suppose there are two ordered arrays A and B, and the two should be merged into array C in order. We use an instance to deduct:

In array A, there are four elements, and array B has six elements. First, compare the first element in array A and array B and place the smaller one to the first element in array C, this element is the smallest of all elements A and B. In the above example, 7 is less than 23, so 7 is placed in C.

Then, compare 23 with other elements in B. If it is smaller than 23, continue to put it in C in order; if it is greater than 23, put 23 into C.

23. After adding it to C, Use 47 after 23 as the reference element. compare it with other elements in B and repeat the above steps.

If all the elements in one array have been copied to C, insert the remaining elements in the other array to C in sequence. So far.

Follow the above steps to implement it in java:

/*** Merge arrayA and arrayB to arrayC * @ param arrayA the length of array A * @ param sizeA array A * @ param arrayB the array B to be merged * @ param arrayB * @ param length of sizeB array B * @ param arrayC the array used to merge and sort */public static void merge (int [] arrayA, int sizeA, int [] arrayB, int sizeB, int [] arrayC) {int I = 0, j = 0, k = 0; // used as the subscript pointer of arrayA, arrayB, and arrayC respectively while (I <sizeA & j <sizeB) {// both arrays are not empty if (arrayA [I] <arrayB [j]) {// place the two smaller ones in arrayC. arrayC [k ++] = arrayA [I ++];} else {arrayC [k ++] = arrayB [j ++] ;}}// after the loop ends, an array is completely copied to arrayC, in the other array, there are two while loops following the element // used to process another non-empty array while (I <sizeA) {arrayC [k ++] = arrayA [I ++];} while (j <sizeB) {arrayC [k ++] = arrayA [j ++];} for (intl = 0; l <arrayC. length; l ++) {// print the element System in the new array. out. print (arrayC [l] + "\ t ");}}

Before merging, another step should be done in advance, that is, array decomposition, which can be achieved through recursive methods.
**Recursion**(Recursive) is a common idea in algorithm design.
In this way, the array is decomposed recursively, and then the array is merged and sorted.

The complete java code is as follows:

Public class Sort {private int [] array; // array to be sorted public Sort (int [] array) {this. array = array;} // print the public void display () {for (int I = 0; I <array. length; I ++) {System. out. print (array [I] + "\ t");} System. out. println ();} // merge and sort public void mergeSort () {int [] workSpace = new int [array. length]; // array recursiveMergeSort (workSpace, 0, workSpace. length-1);}/*** recursive Merge Sorting * @ param workSpace Array for secondary sorting * @ param lowerBound the minimum subscript of the array segment to be merged * @ param upperBound the maximum subscript of the array segment to be merged */private void recursiveMergeSort (int [] workSpace, int lowerBound, int upperBound) {if (lowerBound = upperBound) {// This section has only one element and does not need to be sorted return;} else {int mid = (lowerBound + upperBound)/2; recursiveMergeSort (workSpace, lowerBound, mid); // recursiveMergeSort (workSpace, mid + 1, upperBound) for low-position merging; // merge for High-position merging (workSpace, lowerBound, mid, UpperBound); display () ;}}/*** combines the two segments in the array, lowerBound ~ Mid is the low segment, mid + 1 ~ UpperBound is the array of secondary merging in the high segment * @ param workSpace, hold the merged element * @ param lowerBound start subscript of the merged segment * @ param mid midpoint subscript of the merged segment * @ param upperBound end subscript of the merged segment */private void merge (int [] workSpace, int lowerBound, int mid, int upperBound) {int lowBegin = lowerBound; // start subscript of the low segment int lowEnd = mid; // The end subscript of the low part int highBegin = mid + 1; // The start subscript int highEnd = upperBound of the high part; // The end subscript of the high part int j = 0; // workSpace subscript pointer int n = upperBound-lowerBound + 1; // total number of elements merged while (lowBegin <= lowEnd & highBegin <= highEnd) {if (array [lowBegin] <array [highBegin]) {// place the two smaller ones in the workSpace [j ++] = array [lowBegin ++];} else {workSpace [j ++] = array [highBegin ++] ;}} while (lowBegin <= lowEnd) {workSpace [j ++] = array [lowBegin ++];} while (highBegin <= highEnd) {workSpace [j ++] = array [highBegin ++];} for (j = 0; j <n; j ++) {// copy the merged elements to array [lowerBound ++] = workSpace [j] ;}}.

Run the following code to test the function:
int [] a ={6,2,7,4,8,1,5,3};Sort sort = newSort(a);sort.mergeSort();

The output is as follows:

The order of merging is as follows: first, the initial array is divided into two parts. First, the low segment is merged, and then the high segment is merged. The low and high segments are further decomposed into a more subdivided pair of low and high segments. The high segments are also divided into a more subdivided pair of low and high segments, and so on.

In the above example, the first step is to merge 6 and 2, and the second step is to merge 7 and 4, the third part is the sub-sections [2, 6] and [4, 7] merged in the first two steps. At this point, the left half of the array (low part) is merged, and then the right half is merged (high part ).

Therefore, the fourth step is to merge 8 and 1, and the fourth step is to merge 5 and 3. The fifth step is to merge the fields [1, 8] and [3, 5] in the first two steps. At this point, the right half of the array is merged.

The last step is to merge the left half of the array [2, 4, 6, 7] with the right half of [1, 3, 5, 8].

Merge Sorting ends.

In the description of the Merge Sorting, the first merge is to merge all adjacent two elements before the next merge, instead of merging the left half, merge the right half, but the execution sequence of the program is inconsistent with the analysis logic of the merge sort, so it is difficult to understand.

The following code and legends are used to analyze the merge and sort process in detail.

**Virtual Machine Stack**(VM Stack) is a memory model used to describe Java method execution. Each method call is accompanied by a Stack pressure and an out-of-Stack operation.

The array to be sorted is:

Int [] a = {6, 2, 7, 4, 8, 1, 5, 3}

When the main () method calls the mergeSort () method, the called method is pushed into the stack, and then the program enters the mergeSort () method:

Public void mergeSort () {int [] workSpace = new int [array. length]; // array recursiveMergeSort (workSpace, 0, workSpace. length-1) used for secondary sorting );}

Now, mergeSort () calls the recursiveMergeSort (workSpace,) method, and the recursiveMergeSort (workSpace,) method is pushed to the stack, on mergeSort.
Then, the program enters the recursiveMergeSort (workSpace,) method:

If (lowerBound = upperBound) {// This segment has only one element and does not need to be sorted return;} else {int mid = (lowerBound + upperBound)/2; recursiveMergeSort (workSpace, lowerBound, mid); // recursiveMergeSort (workSpace, mid + 1, upperBound); // sort merge (workSpace, lowerBound, mid, upperBound) for high-position merging ); display ();}

The lowerBound parameter value is 0, and the upperBound parameter value is 7, which does not meet the lowerBound = upperBound condition. Therefore, the method enters the else branch and then calls the recursiveMergeSort (workSpace,) method ),

RecursiveMergeSort (workSpace,) is pushed into the stack. The stack status is as follows:

However, recursiveMergeSort (workSpace,) cannot be returned immediately. It calls recursiveMergeSort (workSpace,), recursiveMergeSort (workSpace,), and recursiveMergeSort (workSpace, 0, 0). The stack status is as follows:

When the program runs here, a method can finally return the result -- recursiveMergeSort (workSpace ), the execution logic of this method is to merge the elements whose subscript ranges from 0 to 0 in the array. There is only one element in this segment, so you do not need to merge and return immediately.

Once the method is returned, it means that the method is over. recursiveMergeSort (workSpace,) pops up from the stack. At this time, the program jumps to the second line in code snippet (2:

RecursiveMergeSort (workSpace, 1, 1 );

This method is similar to the recursiveMergeSort (workSpace,) method. It does not need to be merged and is returned directly.

At this time, it jumps to the third line in code snippet (2:

Merge (workSpace, 0, 0, 1 );

That is, merge the first two elements in the array (naturally, merge (workSpace, 1) is also accompanied by an inbound and outbound stack ).

So far, the code snippet (2) is executed, the recursiveMergeSort (workSpace,) method goes out of the stack, and the program jumps to the second line of code snippet (3:

RecursiveMergeSort (workSpace, 2, 3 );

This method is used to merge the third and fourth elements in the array. Similar to the process of executing recursiveMergeSort (workSpace,), the third and fourth elements are merged and sorted.

Then, the program jumps to the third line of code snippet (3:

Merge (workSpace, 0, 1, 3 );

Merge the two subsequences (the first and second elements are a group, and the third and fourth elements are a group) in the preceding sorted order.

Then recursiveMergeSort (workSpace,) goes out of the stack, and the program jumps to the second line of code snippet (4:

RecursiveMergeSort (workSpace, 4, 7 );

Merge and sort the four elements in the right half of the array. With a series of inbound and outbound stacks, the last four elements are arranged. At this time, the left half and right half of the array are ordered.

Then the program jumps to the third line of code snippet (4:

Merge (workSpace, 0, 3, 7 );

Merge the left half and right half of the array.

Then recursiveMergeSort (workSpace, 4, 7) goes out of the stack, mergeSort () goes out of the stack, and the main () method ends.

Algorithm Analysis
First, analyze the number of copies.

If the array to be sorted has eight elements, merge and sort the elements by three layers. The first layer has four self-arrays containing two data items, and the second layer contains two sub-arrays containing four data items, the third layer contains a child array of 8 data items. When merging sub-arrays, all elements in each layer must be copied once (from the original array to the workSpace array). The total number of copies is 3x8 = 24, that is, multiply the number of layers by the total number of elements.

If the total number of elements is N, the number of layers is log2N, and the total number of copies is N * log2N.

In fact, in addition to copying from the original array to the workSpace array, you also need to copy from the workSpace array to the original array. Therefore, the final number of copies is 2 * N * log2N.

In the large O notation, constants can be ignored.**The time complexity of Merge Sorting is O (N * log2N ).**

Generally, the time consumed by the replication operation is much larger than the time consumed by the comparison operation. The time complexity is dominated by the number of copies.

Next we will analyze the comparison times.

In the Merge Sorting, the number of comparisons is always less than the number of copies. Given two subarrays with four elements, first let's look at the number of comparisons in the worst case and the best case.

In the first case, the data item size is staggered, so seven comparisons are required. In the second case, an array is smaller than all elements in the other array, so only four comparisons are required.

If the total number of elements is N, the number of comparisons in the best case is N/2, and the number of comparisons in the worst case is the N-1.

Assuming that the total number of elements in the array to be arranged is N, the first layer needs to be merged N/2 times, and the total number of elements in each merge is 2; then the first layer needs to be merged N/4 times, the total number of elements for each merge is 4; the first layer requires N/8 merge, and the total number of elements for each merge is 8 ...... The last merge count is 1, and the total number of elements is N. The total number of layers is log2N.

In the best case, the total number of comparisons is:

N/2 * (2/2) + N/4 * (4/2) + N/8 * (8/2) +... + 1 * (N/2) = (N/2) * log2N

In the best case, the total number of comparisons is:

N/2 * (2-1) + N/4 * (4-1) + N/8 * (8-1) +... + 1 * (N-1) =

(N-N/2) + (N-N/4) + (N-N/8) +... + (N-1) =

N * log2N-(1 + N/2 + N/4 + ..) <N * log2N

It can be seen that the number of comparisons is between (N/2) * log2N and N * log2N. If large O notation is used, the time complexity is also**O (N * log2N ).**

Copyright Disclaimer: This article is an original article by the blogger and cannot be reproduced without the permission of the blogger.