Author: July, March 20, 2011.
Source: http://blog.csdn.net/v_july_v.
--------------------------------------------------
Preface:
I believe that I have written the first two articles about the Quick Sort Algorithm: the first one, the first one, and the quick sort algorithm, and the second article, the continuation of the first article, the in-depth analysis of the fast sorting algorithm, you have a sufficient understanding and understanding of the fast sorting algorithm. However, it is obviously not enough to stay at the level of understanding an algorithm, even if you know more thoroughly and deeply. It is best to program and implement it.
On the Internet, the writing layers of quick sorting are unclear, and there is a lack of unified and overall elaboration and implementation. That is, there is no final tone, so I plan to implement it myself.
So it took me one morning to write all the versions of the Quick Sort Algorithm into a program. Including some on the internet, none, Introduction to algorithms, general in Chinese textbooks, randomization, three-digit splitting, recursive, non-recursive, all versions are written in c/c ++.
In the light of the rush of time, I hope you will not be able to give me any further comments on the improper aspects of a person's consideration. However, below, all the c/c ++ source code has been debugged by myself. please correct me if you have any questions.
OK. This article mainly consists of the following parts:
Part 1: recursive version
I. One-way scanning version in introduction to Algorithms
Ii. Two-way scanning of Domestic Teaching Materials
2.1. Hoare version
2.2. Several variant versions of Hoare.
Iii. randomization version
4. Division of three numbers
Part 2: Non-recursive Edition
Okay. Please take a closer look.
Part 1: recursive version of quick sorting
I. Introduction to Algorithms
In my second article, we already know:
"N. Lomuto proposed a new version later, which optimized the PARTITION program and is now written in the introduction to algorithms ":
The key to the fast sorting algorithm is the PARTITION process, which rearranges A [p. r] in place:
PARTITION (A, p, r)
1 x region A [r] // The last element, with A [r] as the primary element
2 I then p-1
3 for j branch p to r-1 // note that j points from p to a R-1, not r.
4 do if A [j] ≤ x
5 then I have I + 1
6 exchange A [I] <-> A [j]
7 exchange A [I + 1] <-> A [r] // Finally, the switching Principal Component
8 return I + 1
Then, recursively sort the entire array:
QUICKSORT (A, p, r)
1 if p <r
2 then q PARTITION (A, p, r) // key
3 QUICKSORT (A, p, q-1)
4 QUICKSORT (A, q + 1, r)
Based on the above pseudo code, it is not difficult to write the following c/c ++ program:
First, the PARTITION process:
Int partition (int data [], int lo, int hi)
{
Int key = data [hi]; // use the last element. data [hi] is the primary element.
Int I = lo-1;
For (int j = lo; j {
If (data [j] <= key)
{
I = I + 1;
Swap (& data [I], & data [j]);
}
}
Swap (& data [I + 1], & data [hi]); // it cannot be changed to swap (& data [I + 1], & key)
Return I + 1;
}
Note: For example, the first sorting is as follows (for more detailed analysis, see the second article ):
Step 1 (step 4 ):
A: 3 8 7 1 2 5 6 4 // The last element, data [hi] as the primary element
B: 3 1 7 8 2 5 6 4
C: 3 1 2 8 7 5 6 4
D: 3 1 2 4 7 5 6 8 // Finally, swap (& data [I + 1], & data [hi])
The swap function is simple enough:
Void swap (int * a, int * B)
{
Int temp = *;
* A = * B;
* B = temp;
}
Then, call partition to recursively sort the entire array:
Void QuickSort (int data [], int lo, int hi)
{
If (lo {
Int k = partition (data, lo, hi );
QuickSort (data, lo, k-1 );
QuickSort (data, k + 1, hi );
}
}
Now, I have a question to ask you. Keep the rest unchanged and slightly modify the above partition process as follows:
Int partition (int data [], int lo, int hi) // please think about it
{
Int key = data [hi]; // use the last element. data [hi] is the primary element.
Int I = lo-1;
For (int j = lo; j <= hi; j ++) // now, I have directed j from lo to hi, not hi-1.
{
If (data [j] <= key)
{
I = I + 1;
Swap (& data [I], & data [j]);
}
}
// Swap (& data [I + 1], & data [hi]); // remove this line
Return I; // return I, not I + 1.
}
As shown above, the rest remain unchanged. Could you please let j scan the last element and exchange it with data [I + 1], remove the final swap (& data [I + 1], & data [hi]), and then return I. Is this feasible?
In fact, this problem is mentioned in my second article:
"Can I change the preceding PARTITION (A, p, r) version to this? The following columns ":
PARTITION (A, p, r) // read the version.
1 x region A [r]
2 I then p-1
3 for j then p to r // Let j point from p to the last element r
4 do if A [j] ≤ x
5 then I have I + 1
6 exchange A [I] <-> A [j]
// 7 exchange A [I + 1] <-> A [r] Remove this last step
8 return I // return I, And I + 1 is not returned.
I hope the readers will think about it and then tell me the result in the comments.
Here I will briefly discuss the following: the readers are invited to think about the version, but the code has been modified in the following three ways: 1. j: p-> r; 2. Remove the last exchange step; 3. Return I. First of all, both my version and the original version of the introduction to algorithms are correct, and I have already completed programming and testing. However, in fact, the two methods have the same idea.
Why? For more information, see the following,
Int partition (int data [], int lo, int hi) // please think about it
{
Int key = data [hi]; // use the last element. data [hi] is the primary element.
Int I = lo-1;
For (int j = lo; j <= hi; j ++ )//....
{
If (data [j] <= key) // if j points from lo to hi, when j points to hi, A [j] <= x
{
I = I + 1;
Swap (& data [I], & data [j]);
}
}
// Swap (& data [I + 1], & data [hi]); // The fact is that you should add this sentence and exchange it directly.
Return I ;//
}
We know that when j finally points to r, there must be A [j] <= x (that is, =). Therefore, this if judgment is redundant and meaningless. Therefore, just like the introduction to algorithms, swap (& data [I + 1], & data [hi]) is directly exchanged; and I + 1 is returned. Therefore, in general, the version in the introduction to algorithms is written in that way, which is more standardized and reasonable than asking readers to think about the version. OK. Please continue reading.
Of course, in the above partition process, you can also remove the swap function call and write it directly in the split function:
Int partition (int data [], int lo, int hi)
{
Int I, j, t;
Int key = data [hi]; // use the last element as the sentry, that is, the principal element.