测试链接:
随即快排java代码(acm版本):
public class QuickSort {
public static int MAXN = 100001;
public static int[] arr = new int[MAXN];
public static int n;
public static void main(String[] args) {
BufferedReader br = new BufferdReader(new InputStreamReader(System.in));
StreamTokenizer in = new StreamTokenizer(br);
PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
in.nextToken();
n = (int) in.nval;
for (int i = 0; i < n; i++) {
int.nextToken();
arr[i] = (int) in.nval;
}
quickSort2(0, n - 1);
for (int i = 0; i < n - 1; i++) {
out.print(arr[i] + " ");
}
out.println(arr[n-1]);
out.flush();
out.close();
br.close();
}
// 随机快速排序经典版(不推荐)
// 甚至在洛谷上测试因为递归开太多层会爆栈导致出错
public static void quickSort1(int l, int r) {
if (l == r) {
return;
}
//l.....r随机选一个位置,x这个值,做划分
int x = arr[l + (int)(Math.random() * (r - l + 1))];
int mid = partition1(l, r, x);
quickSort1(l, mid - 1);
quickSort1(mid + 1, r);
}
//partition1时间复杂度O(n)
pulic static int partition1(int l, int r, int x) {
//a: arr[l....a-1]范围是<=x的区域
int a = l, xi;
for(i = l; i <= r; i++) {
if (arr[i] <= x) {
swap(a, i);
if (arr[i] = x) {
xi = a;
}
a++;
}
}
swap(a-1, xi);
return a-1;
}
//快速排序改进版
public static void quickSort2(int l, int r) {
if (l == r) {
return;
}
//l.....r随机选一个位置,x这个值,做划分
int x = arr[l + (int)(Math.random() * (r - l + 1))];
partition2(l, r, x);
// 为了防止底层的递归过程覆盖全局变量
// 这里用临时变量记录first、last
int left = first;
int right = last;
quickSort2(l, left - 1);
quickSort2(right + 1, r);
}
//荷兰国旗问题
public static int first;
public static int last;
// 已知arr[l....r]范围上一定有x这个值
// 划分数组 <x放左边,==x放中间,>x放右边
// 把全局变量first, last,更新成==x区域的左右边界
// partition2时间复杂度O(n)
public static void partition2(int l, int r, int x) {
first = l;
last = r;
while (i <= last) {
if (arr[i] == x) {
i++;
} else if (arr[i] < x) {
swap(first++, i++);
} else {
swap(i, last--);
}
}
}
public static void swap(int i int j) {
int temp;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
最差情况下时间复杂度:O(n^2),每次随机的数字在数组两个端点。
最好情况下时间复杂度:O(n*logn),根据master公式算出,每次随机的数字正好在数组中间。
因此随机快排时间复杂度:O(n*logn)。