快排主要运用了分治策略,每次选一个主元(主元放在它最终的位置上,在它左边的数都比它小,在它右边的数都比它大),从两边往中间寻找,当左边的元素大于等于主元、右边的元素小于等于主元时停下来交换左右两个元素,直到左边界不再小于右边界;然后递归地处理主元左边和右边的数据~~
接下来有两个快排的写法:
第一种是每次选择左边第一个数作为主元的快排,未做任何优化:
1 int partition(int *A, int left, int right){ 2 int pivot = A[left]; 3 while(left < right){ 4 while(left < right && A[right] > pivot) 5 right--; 6 A[left] = A[right]; 7 while(left < right && A[left] <= pivot) 8 left++; 9 A[right] = A[left]; 10 } 11 A[left] = pivot; 12 return left; 13 } 14 15 void qSort(int *A, int left, int right){ 16 if(left < right){ 17 int pos = partition(A, left, right); 18 qSort(A, left, pos - 1); 19 qSort(A, pos + 1, right); 20 } 21 } 22 23 void quickSort(int *A, int N){ 24 qSort(A, 0, N-1); 25 }
第二种对主元的选择进行了优化,每次选择左边、中间和右边数据的中位数作为主元,同时将这三者排好序。需要注意递归的边界。
1 void swap(int &a, int &b){ 2 int c = a; 3 a = b; 4 b = c; 5 } 6 7 int getPivot(int *A, int left, int right){ 8 int center = (left + right) / 2; 9 if(A[left] > A[center]) 10 swap(A[left], A[center]); 11 if(A[left] > A[right]) 12 swap(A[left], A[right]); 13 if(A[center] > A[right]) 14 swap(A[center], A[right]); 15 swap(A[center], A[right - 1]); 16 return A[right -1]; 17 } 18 19 void qSort(int *A, int left, int right){ 20 if(left >= right) 21 return; 22 int pivot = getPivot(A, left, right); 23 if(left + 1 == right) return; 24 int i = left, j = right -1; 25 while(1){ 26 while(A[++i] < pivot); 27 while(A[--j] > pivot); 28 if(i < j) 29 swap(A[i], A[j]); 30 else 31 break; 32 } 33 swap(A[i], A[right - 1]); 34 qSort(A, left, i - 1); 35 qSort(A, i + 1, right); 36 } 37 38 39 void quickSort(int *A, int N){ 40 qSort(A, 0, N-1); 41 }