排序算法-快速排序
复杂度
时间复杂度(平均) | 时间复杂度(最好) | 时间复杂度(最坏) | 空间复杂度 | 稳定性 | 复杂性 |
---|---|---|---|---|---|
O(nlog2n) | O(nlog2n) | O(n^2) | O(1) | 不稳定 | 较易 |
思路:
- 设待排序数组长度为n
- 选取边界l,r为数组左右边界0~n-1
- 每次于一边界范围中选取一数组元素i,将小于i的数置于数组左边,大于i的数置于数组右边.
每次步骤2都将固定一个数组元素i - 分别对2操作后的i左右两侧数组元素进行2操作,可分别得到子数组与新固定元素
(注:元素i处位置已经固定,下次循环时不需考虑i的下标) - l>=r时结束本次固定
优化:
快排关键在于选取基准值i,若待排序数组本身即有序则快排会退化为冒泡排序.
选取基准值时我们可以随机地选取l~r处的下标将其作为本次快排基准值
方法:index = l + (int)(Math.random() * (r - l + 1))
注:
-
初始边界的选择为左/右时,初始循环就应设置为相反方向(右/左)
- 此举旨在规避初始边界值即为最值的情况
-
将随机最小元素移至边界:若所选随机元素所在位置恰好为其索引位置,则快排循环中必定会破坏其位置。
public void quickSort_1(int[] nums, int l, int r){
if(l >= r) return;
int l1 = l, r1 = r;
int index = l + (int)(Math.random() * (r - l + 1));
swap(nums, l, index);
while(l1 < r1){
while(l1 < r1 && nums[l] <= nums[r1]) r1--;
while(l1 < r1 && nums[l] >= nums[l1]) l1++;
swap(nums, l1, r1);
}
swap(nums, l1, l);
quickSort_1(nums, l, l1 - 1);
quickSort_1(nums, l1 + 1, r);
}private void swap(int[] nums, int i, int j){
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}