0%

快速排序

学C语言的时候经常用库函数qsort,学数据结构的时候知道qsort是怎么一回事儿了,数据结构期末考试有一道题就是写快排的算法,当时很熟悉,但很久不用就忘了,再写一遍加深印象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
public class Main {
public static void main(String[] args) {
int[] nums = randomArray(100);
System.out.println("排序前:" + Arrays.toString(nums));
qSort(nums);
System.out.println("排序后:" + Arrays.toString(nums));
}

private static void qSort(int[] nums) {
qSort(nums, 0, nums.length - 1);
}

private static void qSort(int[] nums, int left, int right) {
if (left >= right) {
return;
}
// 一趟快速排序
int std = order(nums, left, right);
qSort(nums, left, std - 1);
qSort(nums, std + 1, right);
}

// 交换数组中两个元素
private static void swap(int[] nums, int index1, int index2) {
int tmp = nums[index1];
nums[index1] = nums[index2];
nums[index2] = tmp;
}

// 一趟快速排序
private static int order(int[] nums, int left, int right) {
int std = left;
int l = left + 1, r = right;
boolean flag = false;
while (l <= r) {
// <----
if (flag) {
if (nums[std] < nums[l]) {
swap(nums, std, l);
flag = false;
std = l;
}
l++;
} else { // ---->
if (nums[std] > nums[r]) {
swap(nums, std, r);
flag = true;
std = r;
}
r--;
}
}
return std;
}

private static int[] randomArray(int length) {
int[] nums = new int[length];
for (int i = 0; i < nums.length; i++) {
nums[i] = (int) (Math.random() * 100);
}
return nums;
}
}

核心是一趟快速排序的算法,如果选择第一个元素作为参考,就必需先从后往前对比交换位置,举个栗子:

如果序列是:【5, 6, 4, 2】,先从左往右对比交换:

  • 第一次:5和6对比,不做变化。
  • 第二次:5和4对比,交换位置。【4,6, 5,2】
  • 第三次:换方向,5和2对比,交换位置。【4,6,2,5】

出问题了,最大的数6没能移动到最后,这是因为5和6对比的时候5还在6的前面,而当5移动到6之后时,6已经失去了移动的机会。

反过来,如果先从右往左,一开局5就处于一个尽可能靠后的位置,上面的情况则可以避免。