算法复习之 快速排序(不使用交换的快速排序)
快速排序的思想很简单,就是每次确定一个mid位置,让该位置的数在整个数组中保持有序之后,再对其两边的子数组分别进行快速排序。
因此如何将一个选定的数变为全局有序变成了快速排序的关键问题。
提供一种思路:这种思路采用的是覆盖替换的方式,具体的,我们把pivot位置的元素存起来,准备放到一个位置。我们使指针 l 指向数组头,r指向数组尾,然后通过一定的策略缩小这个区间,最后就会得到一个位置用来存放pivot。pivot一定会放到l和r之间或之上,由于要避免交换而且要将比pivot大的都放到pivot右边,比pivot小的放到他左边,第一轮,我们选取一个元素放到初始pivot的位置(这样可以避免交换),也就是选一个元素放到l的位置,那肯定要选取一个比pivot小的元素放到 l ,我们通过向前移动r来寻找这个数,找到之后可以确保r右边的数都比pivot大(或等)。接着,我们要选取一个元素放到位置r,那肯定是选取一个比pivot大的元素。我们可以通过向后移动 l 来寻找第一个比pivot大的数,这样可以确保l之前的数字一定比pivot小(或等)。找到之后,l位置又需要被l和r之间比pivot小的元素替换。依次执行上述步骤,当l == r时,说明此时l的位置就是pivot该在的位置,此时pivot左边的元素都比他小,pivot右边的元素都比他大(或等)。
public static int find(int[] arr, int l, int r) {
int pivot = arr[l];
while(l < r) {
while(l < r && arr[r] >= pivot) r --;
arr[l] = arr[r];
while(l < r && arr[l] <= pivot) l ++;
arr[r] = arr[l];
}
arr[l] = pivot;
return l;
}
public static void quickSort(int[] arr, int l, int r) {
if (l < r) {
int mid = find(arr, l, r);
quickSort(arr, l, mid - 1);
quickSort(arr, mid + 1, r);
}
}
时间并不会因为你的迷茫和迟疑而停留,就在你看这篇文章的同时,不知道有多少人在冥思苦想,在为算法废寝忘食,不知道有多少人在狂热地拍着代码,不知道又有多少提交一遍又一遍地刷新着OJ的status页面……
没有谁生来就是神牛,而千里之行,始于足下!