In the previous blog (http://blog.csdn.net/jasonding1354/article/details/37736555), we introduced the typical example of the sub-governance strategy, that is, the merge sort, and provided the C code example of recursive and cyclic form. However, merging and sorting has two characteristics: first, it takes a lot of effort to merge (that is, the merging steps in the splitting policy, second, additional storage space (out of place sort) is required in the sorting process ).
To save storage space, a fast Sorting Algorithm (in-place sorting in-place sort) is available ). Fast sorting is a sort algorithm developed by Tony Hall. On average, sorting n items requires O (nlogn) comparison. In the worst case, an O (n2) comparison is required, but this is not common. In fact, fast sorting is usually much faster than other O (nlogn) algorithms because its inner loop can be implemented efficiently in most architectures.
The idea of this sort is: if the separation is not separated from the center, the second is to separate two small and one sub-Sequences Based on the element size (all elements in one sub-sequence are greater than all elements in the other sub-series). In this case, because the relative order between two subsequences is correct, it does not take any time to merge them.
Although there is no cost for quick sorting in merging, because the decomposition is based on the element size, it takes a long time to break down the process, that is, to pay the price first; no effort is required during merging, then enjoy the fruits of the work.
1. Fast sorting process
(1) Select a lever (demarcation point and benchmark ). In the sequence to be sorted, select an element in a certain way, that is, the lever point.
(2) decomposition. Based on leverage points, the sequence is divided into two subsequences, a [p .. q-1], a [q + 1 .. r], Its Neutron sequence a [p .. all elements in the Q-1] are less than or equal to the lever point, and all elements in the other sub-sequence a [q + 1, R] are greater than the lever point. After the decomposition exits, the benchmark is in the middle of the series.
(3) Governance. Recursively sort the two subsequences quickly, and sort the subsequences A [p... q-1] And a [q + 1. R.
(4) merge. Merge the two sub-sequences in the sorted order into a large sequence. Because the two subsequences are sorted in the same order, merging them does not require any operation. The whole sequence a [P.. R] is sorted.
Figure 1 example of a fast sorting process
Figure 2 quick sorting algorithm demonstration
2. pseudocode and Examples
The most important part of a quick sorting algorithm is the partition process. The time cost of quick sorting depends on the decomposition step.
<span style="font-size:14px;">PARTITION(A,m,n){ x = A[m]; i = m; for(j=m+1;j<=n;j++) { if(A[j] <= x) { i = i+1; temp = A[i]; A[i] = A[j]; A[j] = temp; } } temp = A[i]; A[i] = A[m]; A[m] = temp; return i;}</span>
The decomposition process of quick sorting is demonstrated as follows:
Figure 3 Quick Sort decomposition step demonstration
As described in the pseudo-code of the decomposition step, select the first element "6" of the array as the lever point and move the subscript index J in step (1, when a value smaller than the leverage point "6" is found, move the subscript index I to exchange array elements (as shown in step (2), and so on) in step 4, J is used to find elements smaller than the lever point and swap the elements smaller than the lever point to the first half of the array. Finally, in step (5), place the lever point between two sub-arrays.
Here, the red part is the lever point, the yellow part of the array elements are divided into the first part, the blue part of the array elements are divided into the second part, and the gray part of the array element division is not yet divided.
The quick sorting algorithm is as follows:
<span style="font-size:14px;">QUICKSORT(A,p,r){ if(p<r) { q = PARTITION(A,p,r); QUICKSORT(A,p,q-1); QUICKSORT(A,q+1,r); }}</span>
3. Fast sorting of C program instances
#include <stdio.h>#define CutOff 3#define QUICK_ONLYtypedef int ElemType;void Swap(ElemType *i, ElemType *j){ElemType tmp;tmp = *i;*i = *j;*j = tmp;}void PrintElement(ElemType A[], int N, char *prompt){printf("%s :\n",prompt);for(int i=1;i <= N;i++){printf("%5d",A[i-1]);if(i % 10 == 0)printf("\n");}printf("\n");}ElemType Median3(ElemType A[], int Left, int Right){int Center;Center = (Left + Right)/2;if(A[Left] > A[Center])Swap(&A[Left], &A[Center]);if(A[Left] > A[Right])Swap(&A[Left], &A[Right]);if(A[Center] > A[Right])Swap(&A[Center], &A[Right]);Swap(&A[Center], &A[Right-1]);return A[Right-1];}void InsertionSort(ElemType A[], int N){int i,j;ElemType tmp;for(i=1;i<N;i++){tmp = A[i];for(j=i;j>0 && A[j-1]>tmp;j--){A[j] = A[j-1];}A[j] = tmp;}}void QSort(ElemType A[], int Left, int Right){int i,j;ElemType pivot;#ifdef QUICK_ONLYif(Left < Right){#elseif(Left+CutOff <= Right){#endifi = Left;j = Right - 1;pivot = Median3(A, Left, Right);for(;;){while(A[++i] < pivot){}while(A[--j] > pivot){}if(i < j)Swap(&A[i], &A[j]);elsebreak;}//for(;;)Swap(&A[i], &A[Right-1]);QSort(A, Left, i-1);QSort(A, i+1, Right);}#ifndefQUICK_ONLYelseInsertionSort(A+Left, Right-Left+1);#endif}void QuickSort(ElemType A[], int Size){QSort(A, 0, Size-1);}int main(){ElemType test_array[] = {20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1};int num_size = sizeof(test_array)/sizeof(ElemType);PrintElement(test_array,num_size,"The original array:");QuickSort(test_array, num_size);PrintElement(test_array,num_size,"The sorted array:");return 0;}
The running result is:
Figure 4 program running result sorting
Note:
(1) because it takes a lot of time to select a lever point for sorting, if the reverse order is input, the first element is selected as the lever point ), then all elements are grouped into sub-sequences on one side, which is very poor. Therefore, this program uses the three-digit median3 (function), that is, to select the value of the three elements at the left end, right end, and center as the leverage point, this effectively reduces the running time of quick sorting by about 5%.
(2) small array Sorting Problem. For small arrays, quick sorting is better than insertion sorting. Therefore, in the qsort function, you can choose to insert and sort small arrays when left + cutoff <= right.
4. Time Complexity Analysis of quick sorting
The time complexity of quick sorting is reflected in decomposition. Therefore, the cost of decomposition determines the cost of quick sorting. For a sequence with n elements, the maximum number of decomposition times can be n-1, that is, each decomposition forms an empty subsequence and a subsequence containing n-1 elements; the minimum number of decomposition times is logn, that is, two sub-sequences with the same length are decomposed each time.
(1) Worst Case Analysis
In the worst case of fast sorting, the Division behavior is generated during the division process, namely the subsequences containing n-1 elements and the subsequences of 0 elements, therefore, the recursive expression of the running time can be expressed:
T (n) = T (n-1) + T (0) + random (n) = T (n-1) + random (N), so the time complexity is T (N) = random (n2 ).
(2) Best case analysis
In the most balanced division, the size of the two subsequences is equivalent. In this case, the running time is recursive:
T (n) ≤ 2 T (n/2) + random (n). The recursive formula is T (n) = O (nlgn ).
(3) average situation analysis
The average running time of quick sorting is similar to the running time of the best condition.
For example, assume that the division process always produces a division of. The Run Time of the quick sorting is recursive: T (n) = T (9n/10) + T (N/10) + random (n). The result is T (n) = random (nlogn ).
Figure 5 recursive tree of average condition of fast sorting
Reprinted please indicate the author and Article Source: http://blog.csdn.net/jasonding1354/article/details/38224967
References:
Algorithm path (2nd edition), by Yan hengming, Mechanical Industry Press
Introduction to algorithms (2nd), Mechanical Industry Press
Data Structure and algorithm analysis: C language description, Mechanical Industry Press