适用于数组中有重复元素
为什么快排不行
快速排序对于000001升序,j要从1一直遍历到前面,在这次遍历中分割的区间为[] [left+1,mid]
树形结构退化成链表,复杂度为n*n
为什么三路快排行
三路快排将数组分割为三个部分
- 小于基准值
- 等于基准值
- 等于基准值
在下一次递归时,只需要处理 小于基准值
和大于基准值
两个区间。
实现
-
i,k,j 分别维护三个区间
-
tmp 为此次基准值
-
k从基准值的下一个元素开始,向前遍历直到与j相遇,三种情况
- ar[k] < tmp
- 此时ar[i+1]=tmp,ar[k]<tmp;交换i+1和k,两个指针向前移动
- ar[k] = tmp
- k++ 继续处理下一元素
- ar[k] < tmp
- 交换j-1和k(将ar[k]放到第三个区间),k处理刚刚交换的元素
- ar[k] < tmp
-
i和基准值交换
最后的要处理的区间
[begin,i-1]
和[j,end]
代码
void quick3(int[] ar, int begin, int end) {
if (begin >= end) {
return;
}
int i = begin;
int j = end + 1 ;
int k = begin + 1;
int tmp = ar[begin];
while (k != j) {
if (ar[k] < tmp) {
swap(ar, k, i + 1);
k++;
i++;
} else if (ar[k] > tmp) {
swap(ar, k, j - 1);
j--;
} else {
k++;
}
}
swap(ar, begin, i);//基准值交换
quick3(ar, begin, i - 1);
quick3(ar, k, end);
}