Ext.: http://www.cppblog.com/converse/archive/2008/09/28/63008.html
The merge sort algorithm (mergesort) divides a sequence into two sub-sequences of the same size, then sorts the two sub-sequences, and finally merges the two subsequence sequences into an ordered sequence. In the process of synthesis, the general realization all need to open up a space with the same size as the original sequence, For merging operations, an example of a merge sort algorithm is here.
The time complexity of the in-place sorting is O (nlog2n), and the spatial complexity is O (LOGN), which saves memory compared to traditional non-in-place sorting (Time complexity O (NLOGN), Space complexity O (n)), but the ordering speed is slightly slower. In the case of memory tension and the need for sequencing stability, in-situ stable sequencing can play its strengths.
Before we introduce the principle of in-situ stable sequencing, we need to understand two basic algorithms, rotation and binary search.
A) rotation
Rotation, also known as cyclic movement, is assumed to have such a sequence: E0, E1, ..., ei-1, ei, ei+1, ..., en-1, en. Now we need to move it to the left by looping the I position into: ei, ei+1, ..., en-1, en, E0, E1, ..., ei-1. In order to save as much memory as possible and to ensure a faster speed, we can achieve the goal in the case of Time complexity O (n), Spatial complexity O (1). A solution is as follows:
Consider the original sequence as two sub-sequences: E0, E1, ..., ei-1 and Ei, ei+1, ..., en-1, en
Turn these two sequences in reverse order: ei-1, ..., E1, E0 and EN, en-1, ..., ei+1, ei
That is to get a sequence: ei-1, ..., E1, E0, en, en-1, ..., ei+1, ei
And then the whole sequence in reverse order: EI, ei+1, ..., en-1, en, E0, E1, ..., ei-1
The time complexity of the above rotation process is O (N/2) + O (N/2) + O (n) = O (2n) = O (n), in reverse order only one element of the auxiliary space, Space complexity O (1).
Here is an algorithm that does not need to open up new space to merge operations. The core of the algorithm is the following code:
1/* *
2 * Algorithm: Merge two ordered sequential sequences
3 * * *
4 template < typename T >
5 void T_merge (T & V, size_t size, size_t POS)
6 {
7 size_t Fir = 0, sec = pos;
8 while (Fir < sec && sec < size)
9 {
Ten while (Fir < sec && V[fir] <= v[sec]) Fir + +;
size_t maxmove = 0;
(Sec < size && V[fir] > V[sec]) Maxmove + +, sec + +;
T_exchange (& V[fir], Sec-fir, sec-fir-maxmove);
Fir + = Maxmove;
15}
16}
where T is an array, size is an array dimension, and POS is the location of the merge Division. that is, [0,pos] and [POS, size] are ordered respectively. For example, the sequence 1, 3, 5, 7, 2, 4, 6, 8 for the merge operation, at this time size=8, pos = 4.
The correctness of the algorithm is proved by the method of cyclic invariants introduced in the introduction >> of << algorithm, in which the elements in the [Fir, sec] are ordered in this algorithm:
1) Initial: At this time fir = 0, sec = pos, as described in the previous function parameter description, satisfies the loop invariants.
2) Iteration: Take a look at what the loop does. Line 10 does so, as long as the FIR element is not less than the SEC element, the FIR is incremented; line 12 is performed as long as the FIR is greater than the SEC, and the SEC increments and increments the maxmove count. Therefore, After completing the previous two steps, the FIR element must be less than the SEC and all subsequent elements. The elements in the second subsequence before the SEC must be less than FIR. Therefore, [Sec-maxmove, sec] Z elements are less than all [Fir, sec-1] Element. By calling the T_exchange function to "rotate" the element in [Sec-maxmove, sec) before the FIR.
That is, the process looks for a sequence of sub-sequences within it that are less than the first one already sorted in the second sequenced sequence, and "rotates" it to the front.
Take the sequence 1, 3, 5, 7, 2, 4, 6, 8 as an example, at which point Fir=1 is pointing to 3, sec=5 is pointing to 4, maxmove=1, by calling the T_exchange function and then [Sec-maxmove, Sec] is [4,5] the element is 2 " Rotates "before the subsequence 3,5,7, so that the loop ends after the sequence becomes 1,2,3,5,7,4,6,8, at which point fir=2, sec = 5, satisfies the loop invariants.
3) Termination: When the loop terminates, either the FIR or the SEC exceeds the size of the array, it is obvious that the sequence becomes orderly.
The complete algorithm is as follows, and what needs to be specifically stated is that this code is not what I think it is, the original author here:
#include < stdio.h >
#include < iostream >
using namespace Std;
- int array[] = {1, 3, 5, 7, 2, 4, 6, 8};
- int array[] = {3, 5, 7, 8, 1, 2, 4, 6};
- void display (int array[], int n)
- {
- for (int i = 0; i < n; + + i)
- {
- printf ("%d", array[i]);
- }
- printf ("\ n");
- }
-
- /* *
- * Algorithm: Swap two objects
- * */
- Template < typename T >
- void T_swap (T & v1, T & v2)
- {
- T t = v1; V1 = v2; v2 = t;
- }
-
- /* *
- * Algorithm: Reverse sequence
- * */
- Template < typename T >
- void T_reverse (T * V, size_t size)
- {
- size_t s = 0, E = size-1;
- while (S < e && s < size && e > 0)
- T_swap (V[s + +], v[e--]);
- }
-
- /* *
- * Algorithm: hand-crank algorithm, rotation sequence from specified position (see Programming Zhu Ji Nanxiong chapter II)
- * */
- Template < typename T >
- void T_exchange (T * V, size_t size, size_t N)
- {
- T_reverse (V, N);
- T_reverse (v + N, size-n);
- T_reverse (v, size);
- }
-
- /* *
- * Algorithm: Merge two ordered sequential sequences
- * */
- Template < typename T >
- void T_merge (T & V, size_t size, size_t POS)
- {
- size_t Fir = 0, sec = pos;
- while (Fir < sec && sec < size)
- {
- while (Fir < sec && V[fir] <= v[sec]) Fir + +;
- size_t maxmove = 0;
- while (sec < size && V[fir] > V[sec]) Maxmove + +, sec + +;
- T_exchange (& V[fir], Sec-fir, sec-fir-maxmove);
- Fir + = Maxmove;
-
- Display (array, sizeof (array)/sizeof (int));
- }
- }
-
- /* *
- * Algorithm: Merge sort
- * */
- Template < typename T >
- void T_merge_sort (T * V, size_t size)
- {
- if (size <= 1) return;
- T_merge_sort (V, SIZE/2);
- T_merge_sort (v + size/2, SIZE-SIZE/2);
- T_merge (v, size, SIZE/2);
- }
-
- int main ()
- {
- Display (array, sizeof (array)/sizeof (int));
-
- T_merge (array, sizeof (array)/sizeof (int), (sizeof (array)/sizeof (int))/2);
- T_merge_sort (array, sizeof (array)/sizeof (int));
-
- Display (array, sizeof (array)/sizeof (int));
- return 0;
- }
Additional notes:
In fact, the previous use of the "rotation" algorithm to move the element forward is not necessary, you can move the part of the element that you want to move back, and then insert the element in the appropriate position. For example, for sequence 1, 3, 5, 7, 2, 4, 6, 8, the first step is to move the element 2 forward to 3 before you can move the 3,5,7 back and then 2 Insert to the appropriate location.
However, there is a problem, if you want to move more elements, then you need more temporary space to save the elements to move forward, so that the space is not O (1). And the rotation algorithm can achieve the space of O (1) to meet the requirements.