一、原理
对于任意一个无序数组,我们随机的选一个元素作为基准元素(例如:数组中的最后一个或者第一个元素, 然后我们将数组中的剩余元素分别与基准元素进行比较,将小于或等于基准元素的数据放在基准元素的左边,将大于基准元素的数据放在基准元素的右边,当全部比较完成之后,基准元素在数组中的位置就确定了下来。然后,在分别对左边数组和右边的数组递归的进行上面的操作,直到每一个元素的位置都唯一确定下来。
注意1:快速排序最难理解的地方是如何将小于基准元素的元素放在左边,将大于基准元素的元素放在右边,本示例代码使用双指针方法
注意2:若要想得到增序排序,即排序后数据从小到大排列,则将最右侧数据作为基准元素,从左向右遍历元素并与基准元素比较,这样才能将小于基准元素的数据全都放在左侧,大于基准元素的数据全都放在右侧;若想得到降序排序,即排序后数据从大到小排序,则与上述操作相反就行,即 将最左侧数据作为基准元素,从右往左遍历元素并与基准元素比较,这样就能将小于基准元素的数据放在最右侧,大于基准元素的数据放在最左侧,这样便是倒序排序。
二、示例代码
1、增序排序
public class QuickSort {
/**
* 获取
*
* @param nums
* @param mark 基准元素
* @param start 数组开始下标位置
* @param end 数组结束下标位置
* @return 基准元素最终下标位置
*/
public static int getPartIndex(int[] nums, int mark, int start, int end) {
int j = start;
for (int i = start; i <= end; i++) {
if (nums[i] <= mark) {
swap(nums, i, j);
j++;
}
}
return j - 1;
}
/**
* 交换相应位置数据
*
* @param nums
* @param i
* @param j
*/
public static void swap(int[] nums, int i, int j) {
int swap = nums[i];
nums[i] = nums[j];
nums[j] = swap;
}
/**
* 递归对不同partition排序
*
* @param nums
* @param mark 基准元素
* @param start
* @param end
*/
public static void partRecursion(int[] nums, int mark, int start, int end) {
//递归结束条件
if (start == end)
return;
int partIndex = getPartIndex(nums, mark, start, end);
if (partIndex == start) {
partRecursion(nums, nums[end], partIndex + 1, end);
} else if (partIndex == end) {
partRecursion(nums, nums[partIndex - 1], start, partIndex - 1);
} else {
partRecursion(nums, nums[partIndex - 1], start, partIndex - 1);
partRecursion(nums, nums[end], partIndex + 1, end);
}
}
public static void main(String[] args) {
int[] nums = {5, 1, 1, 2, 0, 0, 9, 6};
int end = nums.length - 1;
partRecursion(nums, nums[end], 0, end);
String outStr = "";
for (int i : nums) {
outStr = outStr + "," + String.valueOf(i);
}
System.out.println(outStr);
}
}
0 0 1 1 2 5 6 9
2、降序排序
public class JavaTest1 {
public static void main(String[] args) {
int[] nums = {8, 2, 1, 7, 3, 5, 9, 6};
int length = nums.length;
quickSort(nums, nums[0], 0, length - 1);
for (int i = 0; i < length; i++) {
System.out.println(nums[i]);
}
}
/**
* @param nums 待排序数组
* @param mark 基准元素
* @param left 最左侧index
* @param right 最右侧index
*/
private static void quickSort(int[] nums, int mark, int left, int right) {
if (left == right)
return;
int partition = getPartition(nums, mark, left, right);
if (partition == left) {
quickSort(nums, nums[left], left + 1, right);
} else if (partition == right) {
quickSort(nums, nums[left], left, right - 1);
} else {
//对基准元素左侧数组排序
quickSort(nums, nums[left], left, partition - 1);
//对基准元素右侧数组排序
quickSort(nums, nums[partition + 1], partition + 1, right);
}
}
private static int getPartition(int[] nums, int mark, int left, int right) {
int i = right;//用于遍历数组
int j = right;//用于标记替换位置
for (; i >= left; i--) {
if (nums[i] <= mark) {
swap(nums, i, j);
j--;
}
}
return j + 1;
}
private static void swap(int[] nums, int i, int j) {
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
9
8
7
6
5
3
2
1
421

被折叠的 条评论
为什么被折叠?



