The partition function is the central part of the fast line
Its purpose is to divide the array into two parts, <=pivot and >pivot, or <pivot and >=pivot
There are two kinds of implementation methods, one-way scan version and two- way scanning version , but specific to a version, its implementation method is very different, uneven. In a rigorous scholarly attitude, I will list all the implementations that are currently in contact and make comparisons. In addition to the pseudo-code, I will also give the corresponding c&c++ implementation, for the reader's reference.
One-way scanning:
Here is an example of an introduction to algorithms
PARTITION (A, p, r) x=A[r] I= P-1 forj = P to R-1 ifA[J] <=x i= i +1Exchange A[i] with A[j] Exchange A[i+1] with A[r]returni +1intPartitionintA[],intPintR) { intx =A[r]; inti = P-1; intj =p; for(; J < R; + +)j)if(A[j] <=x) Swap (&a[++i], &A[j]); Swap (&a[i +1], &A[j]); returni +1;}
This is the standard one-way scan, the idea is:
Move the element that is less than or equal to pivot to the front through the swap, it is important to note that I, which is a sentinel, is used to record the position after the exchange, that is, the elements before I are exchanged.
Here are some of the things that can be changed:
1. You can move elements that are less than pivot to the front instead of less than equals, so that you can reduce the number of interchanges and, similarly, move elements that are larger than pivot to the back, but you need to traverse the
2. Or the initial value of I is set to P, not p-1;
3. Pivot can be set as the first element;
4. There is i=j situation, this time the exchange is superfluous, can be optimized out.
The following is a slightly optimized version
intPartitionintA[],intPintR) { intx =A[r]; inti =p; intj =p; for(; J < R; + +)j)if(A[j] <x) {if(I! =j) Swap (&a[i], &A[j]); I++; } Swap (&a[i], &A[j]); returni;}
Bidirectional scanning:
In the introduction of the algorithm, there is this algorithm, but there are a few mistakes, here the fourth version of the algorithm as an example
PARTITION (A, p, r) x=A[p] I=P J= R +1 while trueRepeat J= J-1until A[j]<=x Repeat i= i +1until A[i]>=xifI >=J BreakExchange A[i] with A[J] Exchange A[p] with A[j]returnJintPartitionintA[],intPintR) { intx =A[p]; inti =p; intJ = R +1; while(true) { while(A[--j] >x); while(A[++i] <x); if(I >=j) Break; Swap (&a[i], &A[j]); } Swap (&A[J], &a[p]); returnJ;}
The idea is to find an element that is greater than or equal to pivot from left to right, to find elements less than or equal to pivot from right to left, and then swap the two elements until the left and the next are met, and then the pivot is switched to the correct position.
This is a variant of the above program, it looks very different, but the principle is the same
intPartitionintA[],intPintR) { intx =A[p]; inti = p +1; intj =R; while(I <=j) { while(A[j] > x) j--; while(A[i] < x) i++; if(I >=j) Break; Swap (&a[i++], &a[j--]); } Swap (&A[J], &a[p]); returnJ;}
We look at its scanning conditions, one is greater than equals, one is less than equals, that is, the left and right scanning points exist equal to the case of pivot, at this time we do not have to exchange. According to the principle of complementarity, one scan point condition is greater than or equal, then the other scan point condition should be less than the complementary condition, so that two scan point exchange will not have an exchange of equal elements.
In addition, there is a huge overflow hole in the program, while the inner layer of a while loop such as:
while (A[i] < x) i++;
We cannot guarantee that it will not cross the border, in fact, I have been tested, I found that the value of I once crossed the uncertainty, although all can guarantee I >= j critical condition, but we should try to avoid the cross-border problem
You can add an out-of-bounds condition to a loop
intPartitionintA[],intPintR) { intx =A[p]; inti =p; intJ = R +1; while(true) { while(I < J && A[--j] >=x); if(I >= J) Break; while(I < J && A[++i] <x); if(I >= J) Break; Swap (&a[i], &A[j]); } Swap (&A[J], &a[p]); returnJ;}
Variants of the anti-border version are as follows
intPartitionintA[],intPintR) { intx =A[p]; inti = p +1; intj =R; while(true) { while(I <= J && A[j] >= x) j--; if(i > J) Break; while(I <= J && A[i] < x) i++; if(i > J) Break; Swap (&a[i++], &a[j--]); } Swap (&A[J], &a[p]); returnJ;}
There's a lot more to the left and right scan, so let's take a few more examples.
A widely circulated version of the Internet is the following
intPartitionintA[],intPintR) { intx =A[p]; inti =p; intj =R; while(I <j) { while(I < J && A[j] >= x) j--; if(I >= J) Break; A[i++] =A[j]; while(I < J && A[i] < x) i++; if(I >= J) Break; A[j--] =A[i]; } A[i]=x; returni;}
A closer look will reveal that it is almost identical to the version we have described above, unlike the swap element, which is not used, but instead is overwritten, and finally the pivot is returned.
Specific procedures can be found in: http://blog.csdn.net/morewindows/article/details/6684558
The time complexity of the algorithm is O (n), but why write a double loop? We can completely change it into a single loop, the code is as follows:
intPartitionintA[],intPintR) { intx =A[p]; inti = p +1; intj =R; while(I <=j) {if(A[j] >x) {J--; Continue; } if(A[i] <x) {i++; Continue; } Swap (&a[i++], &a[j--]); } Swap (&A[J], &a[p]); returnJ;}
However, this practice is not recommended, because each time I was judged, I was bound to Judge J again, more than once.
Summary: The individual recommends a one-way scan of the optimized version, two-way scanning can see the problem of cross-border, in order to prevent cross-border pay a certain price.
Quick Sort all versions comparison of partition functions