Sorting algorithm (four)--merge sort and recursion

Source: Internet
Author: User

Basic ideas

Before parsing the merge sort. Let's take a look at the divide-and-conquer algorithm first .

The basic idea of divide-and-conquer algorithm is to decompose a problem of size n into a small sub-problem of K scale. These sub-problems are independent of each other and are of the same nature as the original. Find out the solution of the sub-problem. The solution of the original problem can be obtained.

General steps of the divide-and-conquer algorithm:

(1) Decomposition, the problem to be solved divided into a number of small-scale similar problems;

(2) solve, when the sub-problem is divided into enough hours, with a more simple method to solve.

(3) merger. According to the requirement of the original problem, the solution of sub-problem is combined to form the solution of the original problem.

?

Merge sort is a typical application of divide-and-conquer algorithm.

The merge sort first cuts an unordered n-long array into n ordered sub-sequences (only one sequence of data feels ordered), and then 22 merges. The merged N/2 (or N/2 + 1) subsequence is then continued with 22 merges, and so on to get a complete ordered array.

Steps for example with what you see:

Watermark/2/text/ahr0cdovl2jsb2cuy3nkbi5uzxqv/font/5a6l5l2t/fontsize/400/fill/i0jbqkfcma==/dissolve/70/gravity /center "/>


Java implementation

The core idea of merge sorting is to merge two ordered arrays into an array, so you need to open up additional space .

The first step is to clarify the idea of merging. Suppose there are now two ordered arrays A and B, to merge the two into array C in an orderly manner.

We use an example to deduce:

Watermark/2/text/ahr0cdovl2jsb2cuy3nkbi5uzxqv/font/5a6l5l2t/fontsize/400/fill/i0jbqkfcma==/dissolve/70/gravity /center "/>

In A array of four elements, b array has six elements, first of a, b in the first element, the smaller one is placed in the first of the C array, because the element is a, b the smallest of all elements. In the example above. 7 is less than 23, so 7 is placed in C.

Then, compare 23 with the other elements in B. Assuming less than 23, continue in order to C; assume greater than 23. The 23 is placed in C.

23 after placing in C. Use 47 after 23 as the Datum element, and continue to compare with the other elements in B, repeating the above steps.

Assuming that the elements of an array have all been copied to C, then one of the remaining elements in the array will be inserted in C in turn. This concludes.

In accordance with the above ideas, Java implementation:

/** * merge Arraya and arrayb into ARRAYC * @param arraya Array A * @param sizea the length of array A * @param arrayb                          The array to be merged b * @param the length of Sizeb array b * @param the array of arrayc auxiliary merge sort */public static void merge (int [] Arraya,int Sizea,  int [] arrayb,int sizeb, int [] arrayc) {int i=0,j=0,k=0; As Arraya, Arrayb, ARRAYC, respectively, the subscript pointer while (i<sizea&& J<sizeb) {//Two arrays are not empty if (arraya[           I]<ARRAYB[J]) {//Put the smaller one in Arrayc arrayc[k++]= arraya[i++];          }else{arrayc[k++]= arrayb[j++]; }}//After the loop has ended. An array has been completely copied to ARRAYC, and there is an array of elements//followed by two while loops for processing and a non-empty array while (I<sizea) {arrayc[k++]= A        Rraya[i++];       } while (J<sizeb) {arrayc[k++]= arraya[j++];       } for (intl=0;l<arrayc.length;l++) {//Prints the element System.out.print (arrayc[l]+ "\ T") in the new array; }   }

Before merging, there is one step that needs to be done in advance, that is, the decomposition of the array, which can be achieved by recursive method. Recursive(Recursive) is an idea that is often used in algorithmic design.

This completes the merge sort by first recursively decomposing the array and then merging the array.

The complete Java code is as follows:

public class Sort {private int [] array;   The array to be sorted public sort (int [] array) {this.array= array; }//Print the elements in the array in order public void display () {i=0;i<array.length;i++ (int) {System.out.print (array[i]+       "\ t");   } System.out.println (); }//merge sort public void MergeSort () {int[] workSpace = new int [array.length];//array for auxiliary sorting recursiveme   Rgesort (workspace,0,workspace.length-1); /** * Recursive Merge sort * @param workSpace array of auxiliary sorting * @param lowerbound to merge the smallest subscript of an array segment * @param upperbound to merge the maximum of the array segment Marked */private void Recursivemergesort (int [] Workspace,int lowerbound,int upperbound) {if (lowerbound== upp       Erbound) {//the segment has only one element, without ordering return;          }else{int mid = (lowerbound+upperbound)/2;    Recursivemergesort (Workspace,lowerbound,mid);  Recursivemergesort (Workspace,mid+1,upperbound) of the lower segment merge sort;          Merge (Workspace,lowerbound,mid,upperbound) for high-level segment merging; Display(); }}/** * Merges two segments in an array of arrays.  Lowerbound~mid is the lower segment, the Mid+1~upperbound is the high segment * @param the array of auxiliary merges of the WorkSpace, accommodating the merged elements * @param the starting subscript of the lowerbound merge segment @param Mid-midpoint subscript * @param upperbound Merge segment End subscript */private void merge (int [] workspace,int lowerbound,int Mid,int Upper  Bound) {int lowbegin = lowerbound;           The starting subscript int lowend = Mid for the low segment;  The end subscript int highbegin = mid+1 of the low segment;  The starting subscript int highend = Upperbound of the high-level segment; The end subscript of the high segment int j = 0;  workspace subscript pointer int n = upperbound-lowerbound+1; Total number of merged elements while (Lowbegin<=lowend && highbegin<=highend) {if (array[lowbegin]<array[h           Ighbegin]) {//Put the smaller one in WorkSpace 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 into the array array[lowerbound++]= workspace[j]; }         }}
Test with the following code:

int [] a ={6,2,7,4,8,1,5,3}; Sort sort = Newsort (a); Sort.mergesort ();

The printing results are as follows:



The order of merging is this: The initial array is divided into two parts first. Merge the lower segment first, then merge the high segment. The lower segment and the high segment continue to decompose, and the low segment is decomposed into a more subdivided pair of low and high segments, and the high segment is decomposed into a more subdivided pair of low and high segments. In turn.

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

So the fourth step is to merge the 8 and 1, the fourth merge is 5 and 3, the fifth step is to merge the first two steps into a good field [1,8] and [3,5].

At this point, the right half of the array is merged to complete.

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

Merge sort ends.

?

In this paper, we begin to describe the merging sort. The first lie-down merge is to all adjacent two elements after the end of the merge, before the next round of merging, not first merge the left half, and then merge the right half of the part. However, the order of operation of the program is inconsistent with our analytic logic for merge sort. So it's a little difficult to understand.

The following combination of code and legend to specifically analyze the merge sort process.

Virtual Machine stack (VM?) Stack) is a memory model describing the operation of the Java method, with each method being called with a stack and a stack.

We want to sort the array as:

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

?

When the main () method calls the MergeSort () method, the called method is pressed into the stack, and the program enters the MergeSort () method:

public void MergeSort () {       int[] workSpace = new int [array.length];//array recursivemergesort for auxiliary sorting       (workspace,0, workspace.length-1);   }
At this point, mergesort () also calls the Recursivemergesort (workspace,0,7) method, and the Recursivemergesort (workspace,0,7) method is also pressed into the stack, above MergeSort ().

Then, the program enters into the Recursivemergesort (workspace,0,7) method:???

if (lowerbound== upperbound) {  //the segment has only one element and no sort          return;       } else{          int mid = (lowerbound+upperbound)/2;          Recursivemergesort (workspace,lowerbound,mid);          Recursivemergesort (workspace,mid+1,upperbound) of the lower segment merge sort;          Merge (Workspace,lowerbound,mid,upperbound) for high-level segment merging;          Display ();        }

The Lowerbound participation value is 0,upperbound 7, which does not meet the conditions of lowerbound== upperbound. So the method goes into the else branch and then calls the method Recursivemergesort (workspace,0,3),

Recursivemergesort (workspace,0,3) is pressed into the stack, where the status of the stack is as follows:


However, Recursivemergesort (workspace,0,3) cannot return immediately. It calls Recursivemergesort (workspace,0,1) internally, and Recursivemergesort (workspace,0,1) calls Recursivemergesort (WorkSpace, 0,0), at this point, the status in the stack is as follows:

Watermark/2/text/ahr0cdovl2jsb2cuy3nkbi5uzxqv/font/5a6l5l2t/fontsize/400/fill/i0jbqkfcma==/dissolve/70/gravity /center "/>

Program to run here. Finally, there is a way to return the result--recursivemergesort (workspace,0,0), the logic of the method is to merge the subscript from 0 to 0 in the array. The paragraph has only one element, so no merging is necessary. return immediately.

Method once return. means that the method ends and Recursivemergesort (workspace,0,0) pops up from the stack. At this point, the program jumps to the second line in the code snippet (ii):

Recursivemergesort (workspace,1,1);

The method into the stack. Similar to Recursivemergesort (workspace,0,0), without merging, return directly. Method out of the stack.

The degree jumps to the third line in the code snippet (ii):

Merge (workspace,0,0,1);

That is, the first two elements of an array are merged (naturally, the merge (workspace,0,0,1) is accompanied by a stack and a stack).

At this point, the code fragment (ii) runs complete, Recursivemergesort (workspace,0,1) method out of the stack, the program jumps to the second line of code fragment (c):

Recursivemergesort (workspace,2,3);

This method merges the third and fourth elements in an array. Similar to the process of running Recursivemergesort (workspace,0,1), the third and fourth elements are finally sorted.

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

Merge (workspace,0,1,3);

Merges the two subsequence (the first second element is a group, and the third fourth element is a group), which is already sorted in the preceding sequence.

Then Recursivemergesort (workspace,0,3) out of the stack, the program jumps to the second line of code snippet (iv):

Recursivemergesort (workspace,4,7);

The four elements of the right half of the array are sorted, followed by a series of stacks, stacks, and finally the last four elements are arranged.

At this point, the left and right halves of the array are in order.

Then the program jumps to the code snippet (iv) on the third line:

Merge (workspace,0,3,7);

The left half of the array is merged with the right half part.

Then Recursivemergesort (workspace,4,7) out of the stack, MergeSort () out of the stack, the last main () method out of the stack. The program ends.


Algorithm analysis

First, analyze the number of copies.

Suppose you have 8 elements in the array you want to arrange. Merge sort needs to be divided into 3 layers, the first layer has four self-array containing two data items, the second layer includes two sub-arrays including four data items, and the third layer includes a subarray of 8 data items. When merging sub-arrays, all elements of each layer undergo a copy (copied from the original array to the workspace array), and the total number of copies is 3*8=24 times, i.e. the number of layers multiplied by the total number of elements.

Set the total number of elements to n, the number of layers is log2n. 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, so. Finally, the number of replication replicates is 2*n*log2n.

In large O notation, constants can be ignored. So the time complexity of merge sort is O (n log2n).

Generally speaking. The time consuming of a copy operation is much greater than the time consumed by the comparison operation, and the time complexity is dominated by the number of replications.

?

Let's take a look at the comparison of the Times.

In a merge sort, the comparison is always less than the number of copies.

Now given two sub-arrays with four elements. First look at the worst case and best case comparison.


The first case. The data item size is staggered, so it must be 7 times more, and in another case, an array is smaller than all the elements in an array, so it only takes 4 times to compare them.

When merging two sub-arrays. Assume that the total number of elements is n. The best-case comparison is N/2, and the worst-case comparison is N-1.

Assume that the total number of elements in the array to be queued is n. The first layer needs to be N/2 and merged. The total number of elements per merge is 2, and the first layer needs to be N/4. The total number of elements per merge is 4, then the first layer needs to be N/8, and the total number of elements for each merge is 8 ... The last merge number is 1, and the total number of merged elements is N. The total number of layers is log2n.

The best-case comparison totals are:

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

The best-case comparison totals are:

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

Visible, the comparison is between (N/2) *log2n and n*log2n. Assume with large O notation. The complexity of time is also O (n log2n).

Sorting algorithm (four)--merge sort and recursion

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.