Before writing merge sort, first talk about the thought of divide and conquer,
The so-called divide-and-conquer: is to decompose a more complex problem into a number of smaller but similar sub-problems, ( solve ) to solve these sub-problems recursively, and then merge The solutions of these sub-problems to solve the original problem
Can be divided into three steps:
Decomposition: Decomposition of the original problem into a number of smaller but similar to the original problem of sub-problems
Solution: These sub-problems are solved recursively, however, if the sub-problem size is small enough, it can be directly solved
Merging: Solving the original problem by merging The solutions of these sub-problems
Next, you can finally write the merge sort
Decomposition: A sequence of n numbers is decomposed into 2 2 sub-series with N/2 number
Solution: Two sub-sequences are sorted recursively by using merge sort;
Merging: Merging two sub-columns into a good sequence
According to the above ideas, the idea of merging sort is as follows
Decomposition: N may be an even number of odd numbers, taking full account of the MergeSort function as follows
void mergesort (int* A,int p,int r) { if(p<R) { int q= (p+r)/2; MergeSort (a,p,q); MergeSort (a,q+1, R); Merge (A,p,q,r); } }
Note that to take into account that P=r (p is the starting item to be sorted in an array, R is the subscript of the terminating item to be sorted in an array), and if p=r, there is no need to sort
, next, is responsible for merging two ordered series (note: Here is a cyclic invariant, first assuming that two sub-series are ordered, starting: Only one number, has been ordered, unchanged: Merge sorting function merge to ensure that they are ordered, terminated: recursive end), there are two ways: Sentinel and Non-Sentinel method
Sentinel method: The so-called Sentinel is to add an almost infinite number in the L sequence and r sequence tails to prevent cross-border when judging l[i] and [j]
intn1=q-p+1; intn2=r-Q; int*l= (int*)malloc((n1+1)*sizeof(int)); int*r= (int*)malloc((n2+1)*sizeof(int)); intt,tmp1=0, tmp2=0; for(t=p;t<=q;t++) { * (L+TMP1) =* (A +t); TMP1++; } for(t=q+1; t<=r;t++) { * (R+TMP2) =* (A +t); TMP2++; } * (L+N1) =shaobing; * (R+N2) =shaobing; intI=0, j=0; intK;/*take the elements from two numbers in turn, and put the small one in the original array*/ for(k=p;k<=r;k++) { if(* (L+i) <=* (r+j)) {* (a+k) =* (l +i); I++; } Else { * (a+k) =* (r+j); J++; } } Free(L); Free(R);
Non-Sentinel Law: No Sentinel to prevent cross-border, can only be divided intointn1=q-p+1 intn2=r-Q int *l= (int *) malloc ((n1+ 1) * sizeof (int )); int *r= (int *) malloc ((n2+ 1) * sizeof (int ));
intt,tmp1=0, tmp2=0; for(t=p;t<=q;t++) { * (L+TMP1) =* (A +t); TMP1++; } for(t=q+1; t<=r;t++) { * (R+TMP2) =* (A +t); TMP2++; } * (L+N1) =shaobing;* (R+N2) =shaobing;intI=0, j=0; intK;/*take the elements from two numbers in turn, and put the small one in the original array*/ for(k=p;k<=r;k++) {
if (I==N1)
{
while (J<N2)
{
* (a+k) =* (R+J);
j + +;
k++;
}
Break
}
if (J==N2)
{
while (I<N1)
{
* (a+k) =* (l+i);
i++;
k++;
}
Break
}
if(* (L+i) <=* (r+j)) {* (a+k) =* (l +i); I++; } Else { * (a+k) =* (r+j); J++; } } Free(L); Free(R);
The above is my way of thinking, attach a blog post, merge write better, reference
Sort--merge sort (divide and conquer method)