快速排序是一种常用的排序算法,是对冒泡排序的一种改进。C语言标准库中的函数qsort实现的就是快速排序。快速排序使用了分而治之的算法思想。通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。下面我们来看一下快速排序。
操作处理
我们先来处理一趟划分,找到第一个枢轴的最终位置。步骤如下:
第一步:
将第一个元素作为枢轴(pivot)暂存,此时low所指向的位置是空闲位置,再将49后面的元素依次与枢轴作比较。
第二步:
我们从后往前将元素依次与枢轴进行比较,high表示的是比枢轴元素大的元素。由于65比49大,high做减1操作,向前移动一位,指向27
第三步:
由于27比49小,将27移到low所指向的空闲位置处。
第四步:
原来27的位置就空闲出来了。接下来,我们作比较的话,就应该找大的放在现在的high所指的空闲位置。所以,我们现在就不能和high所指的元素进行比较,而是和low所指的元素进行比较。由于27小于49,则low下移,指向38.
第五步:
由于38小于49,继续下移。
第六步:
由于65大于49,所以65应该移到后面去,27所在的位置是空闲的,将65移到27所在的位置。
第七步:
由于65大于49,high继续向前移动,high指向13。由于13小于49,移动到low所指向的空闲位置。
第八步:
由于13小于49,low向前移动,low指向97,由于97大于49,将97移动到high所指向的空闲位置。
第九步:
由于97大于49,high向前移动,指向76。76大于49,high仍然向前移动,指向97。
第十步:
此时,low和high相等时,说明我们已经把小于49的元素放到左边,大于49的元素放到右边了。而此时的这个位置就是枢轴的最终位置,我们把49放到这里。
一趟划分完成后,将这一组数据从枢轴49这里分成左右两块。然后我们就可以用递归的思想实现了。
代码展示
第一种:枢轴在左(Java版)
import java.util.Scanner;
public class QuickSort {
public static void main(String[] args) {
int[] a = new int[10];
Scanner in = new Scanner(System.in);
System.out.println("请输入10个元素:");
for (int i = 0; i < 10; i++) {
a[i] = in.nextInt();
}
show(a);
System.out.println();
sort(a, 0, a.length - 1);
show(a);
in.close();
}
public static void sort(int a[], int low, int high) {
int i, j;
int pivot;
i = low;
j = high;
pivlot = a[i];
if (low >= high)/// 递归结束条件
return;
else {
while (i < j) {
while (i < j && a[j] >= pivot) {///从右往左扫描,找到第一个比基准元素小的元素
j--;
}
a[i] = a[j];///将a[j]元素放到空闲位置
while (i < j && a[i] < pivot) {///从左往右扫描,找到第一个比基准元素大的元素
i++;
}
a[j] = a[i];///将a[i]元素放到空闲位置
a[i] = pivot;///基准元素归位
sort(a, low, i - 1);///对基准元素左边的元素进行递归排序
sort(a, i + 1, high);///对基准元素右边的元素进行递归排序
}
}
public static void show(int a[]) {
for (int i = 0; i < a.length; i++)
System.out.print(a[i] + " ");
}
}
下面,我们来演示枢轴在中间的情形。
第二种:枢轴在中间(Java版)
import java.util.Scanner;
public class QuickSort {
public static void main(String[] args) {
int[] nums = new int[10];
Scanner sc = new Scanner(System.in);
System.out.println("请输入10个整数:");
for (int i = 0; i < nums.length; i++) {
nums[i] = sc.nextInt();
}
for (int t : nums) {
System.out.print(t + " ");
}
System.out.println();
sort(nums, 0, nums.length - 1);
for (int t : nums) {
System.out.print(t + " ");
}
System.out.println();
sc.close();
}
public static void sort(int[] nums, int _left, int _right) {
int left = _left, right = _right;
int pivlot = nums[(left + right) / 2];
while (left <= right) {
while (nums[left] < pivlot) {
left++;
}
while (pivlot < nums[right]) {
right--;
}
if (left <= right) {
int t = nums[left];
nums[left] = nums[right];
nums[right] = t;
left++;
right--;
}
}
if (_left < right)
sort(nums, _left, right);
if (left < _right)
sort(nums, left, _right);
}
}
总结:
快速排序虽然很快,但是这是要考虑综合情况的。快速排序最好情况下的时间复杂度为O(nlogn),但是最坏情况下时间复杂度却为O(n^2)。