Quick Sort
快排基本思路
- 如果S中元素个数是0或者1,则返回 【边界条件】
- 取S中任一元素v,称之为枢纽元
pivot
【partition】 - 将
S-{v}
划分成两个不相交的集合:S1={x属于S-{v} | x<=v}
和S2={x属于S-{v} | x>= v}
- 返回
{quickSort(S1)+v+quickSort(S2)}
【递归】
选取枢纽元Pivot
选取左(右)端点
- 缺点:如果是已排好序的或者倒序的,
O(n2)
- 选取左右端点作为枢纽元时,数组可以全部使用快排进行排序
选取左端点:
swap(A, left, j)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18public void qsL(int[] A, int left, int right) {
if(left < right) {
int pivot = A[left];
int i = left + 1, j = right;
while(true) {
while(i < A.length && A[i] < pivot) i++;
while(j >=0 && A[j] > pivot) j--;
if(i<j) {
swap(A, i, j);
}else{
break;
}
}
swap(A, left, j);
qs(A, left, j-1);
qs(A, j+1, right);
}
}选取右端点:
swap(A, i, right)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18public void qsR(int[] A, int left ,int right) {
if(left < right) {
int pivot = A[right];
int i = left, j = right -1;
while(true) {
while(A[i] < pivot) i++;
while(j >=0 && A[j] > pivot) j--;
if(i < j) {
swap(A, i, j);
}else{
break;
}
}
swap(A, i, right);
qsR(A, left, i-1);
qsR(A, i+1, right);
}
}
随机选取枢纽元
- 缺点:随机数生成开销很大
三数中值分割法
- 取
left/right/center
三个数中中间大的数作为pivot
,然后将pivot
放到right-1
的位置,遍历0->right-2
的位置即可 如果使用三数中值分割法(优化版快排),则在小于某一个CUTOFF值时,需要改用插入排序,因为三数中值分割法时,至少需要三个数进行,在快排到两个数时,如果还使用该方法,则会出现排序错误
1
2
3
4
5
6
7
8
9
10
11
12
13
14private int median3(int[] A, int left, int right) {
int center = (left + right)/2;
if(A[center] < A[left]){
swap(A, center, left);
}
if(A[left] > A[right]){
swap(A, left, right);
}
if(A[center] > A[right]) {
swap(A, center, right);
}
swap(A, center, right-1);
return A[right -1];
}然后进行递归快排:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21public static final int CUTOFF = 5;
public void qs3(int[] A, int left, int right) {
if(left + CUTOFF <= right) {
int pivot = median3(A, left, right);
int i = left, j = right -1;
while(true) {
while(A[i] < pivot) i++;
while(A[j] > pivot) j--;
if(i<j){
swap(A, i, j);
}else{
break;
}
}
swap(A, i, right -1);
qs3(A, left, i-1);
qs3(A, i+1, right);
}else{
insertionSort(A, left, right);
}
}
附
交叉元素的位置
1 | private void swap(int[] A, int i, int j) { |
插入排序
1 | private void insertionSort(int[] A, int left, int right) { |