快速排序是对冒泡排序的一种改进,是通过每一趟排序,将要排序的数组(或后续讲解的集合)分割成两个独立的部分。其中,一部分的所有数据比另一部分的所有数据都要小。然后通过递归重复这种操作,对分割后的两部分数据分别进行快速排序,最终达到整个数据都是有序排列的。
假定要排序的数组是int[] nums = new int[]{4,5,6,7,3,2,1};
单向扫描法
选定数组的一个元素,将之称为“主元”。之后,扫描一趟数组,将大于或等于主元的元素放在主元的右边,把小于或等于主元的元素放在主元的左边,这个过程被称为用主元分割数组。具体做法是:
a. 选定数组的第一个元素(即 nums 数组中的元素 4)作为主元。
b. 定义两个标记变量 sp 和 bigger,它们都是数组下标。其中 sp 表示 1 中,在从左往右扫描一趟数组的过程中,当前正在扫描的位置,它会向右移动;bigger 是边界,其右侧的数据大于或等于主元。初始时,sp 指向数组的第二个元素,bigger 指向数组的最后一个元素,如图所示。
c. 假设数组名是 arr,第一趟的比较流程是:在 sp≤bigger 的情况下循环,比较arr[sp]<=主元是否成立,如果是,sp 右移一位;否则,就交换 arr[sp]和 arr[bigger],并将 bigger 的位置左移一位(注意 sp 原地不动),第一次比较过程如图所示。
数据交换前:
数据交换后:
bigger 左移一位:
d. 继续循环,重复 c 中描述的过程,如下。
接"bigger 左移一位:"因为当前的arr[sp]<=主元(1<4)成立,所以 sp 右移一位即 sp++;
此时arr[sp]<=主元(6>4)不成立,所以交换 arr[sp]和 arr[bigger],再将 bigger 左移一位,如下图所示。
数据交换前: