通透百万数据秒级排序 : 快速排序

冷环渊
2022年04月04日 · 阅读 83
快速排序
快速排序 是随机选中其中一个元素,进行元素筛选 一遍一遍将小于这个元素的放在左边,把大于元素的放在右边
之后两边再分别随机选择出来一个而元素继续上述操作
- 选出对比元素,可以固定可以随机 可能会影响效率
- 小的放在左边,大的放在右边
- 持续递归
- 拼接返回
动态图
理解实例
简易方便理解版本的快排
利用集合来演示快排
这个效率不会很好,但是很适合我们来理解快速排序的思路
public static ArrayList<Integer> quickSort(ArrayList<Integer> arr) {
if (arr == null || arr.size() <= 1) {
return arr;
}
int leader = arr.get(0);
//存放左右的结果
ArrayList<Integer> left = new ArrayList<>();
ArrayList<Integer> right = new ArrayList<>();
for (int i = 1; i < arr.size(); i++) {
//根据左右条件添加
if (arr.get(i) <= leader) {
left.add(arr.get(i));
} else {
right.add(arr.get(i));
}
}
//递归
ArrayList<Integer> leftResult = quickSort(left);
ArrayList<Integer> rightResult = quickSort(right);
// 合并
ArrayList<Integer> result = new ArrayList<>();
result.addAll(leftResult);
result.add(leader);
result.addAll(rightResult);
return result;
}
标准版本
标准版的思路和简易版本有一定区别
这里是有两个指针一个指向前面 一个指向后面。根据选出的值来从右往左找小于这个数的值移动,之后从左边找大于值的数移动到右边,每一次交换两个数分别放在左右两边,直到左右指针相遇 就将这个数值放在相遇点,直到有序为止。
图解
重复这个过程一直到有序为止,
我们只需要编写一个定位方法,第一次就按照上图来讲low位置的左右两边交换好
之后只需要出去中位,左右递归就可以排序好数列了,至此百万数字秒级排序的快速排序思路完成
代码实现
package com.hyc.algorithm.sort;
import java.util.ArrayList;
/**
* @projectName: DataStructure
* @package: com.hyc.algorithm.sort
* @className: QuickSort
* @author: 冷环渊 doomwatcher
* @description: TODO
* @date: 2022/4/3 23:30
* @version: 1.0
*/
public class QuickSort {
public static void main(String[] args) {
//ArrayList<Integer> arr = new ArrayList<>();
//arr.add(3);
//arr.add(1);
//arr.add(9);
//arr.add(2);
//arr.add(6);
//arr.add(8);
//arr.add(7);
//arr.add(5);
//System.out.println(quickSort(arr));
//int[] arr = {3, 1, 9, 2, 6, 8, 7, 5};
int[] test = new int[8000000];
//测试数据
for (int i = 0; i < 8000000; i++) {
test[i] = (int) (Math.random() * 800000);
}
long time = System.currentTimeMillis();
quickSort(test);
long end = System.currentTimeMillis();
long t = ((end - time) / 1000);
System.out.println("一共用时 " + t + "秒");
}
//简易版本
public static ArrayList<Integer> quickSort(ArrayList<Integer> arr) {
if (arr == null || arr.size() <= 1) {
return arr;
}
int leader = arr.get(0);
//存放左右的结果
ArrayList<Integer> left = new ArrayList<>();
ArrayList<Integer> right = new ArrayList<>();
for (int i = 1; i < arr.size(); i++) {
if (arr.get(i) <= leader) {
left.add(arr.get(i));
} else {
right.add(arr.get(i));
}
}
//递归
ArrayList<Integer> leftResult = quickSort(left);
ArrayList<Integer> rightResult = quickSort(right);
// 合并
ArrayList<Integer> result = new ArrayList<>();
result.addAll(leftResult);
result.add(leader);
result.addAll(rightResult);
return result;
}
//标准版快速排序
public static void quickSort(int[] arr) {
quickSort(arr, 0, arr.length - 1);
}
public static void quickSort(int[] arr, int low, int high) {
if (low >= high) {
return;
}
//已经交换过一次 中间值的为止不会变化了
int partPoint = partition(arr, low, high);
//递归左边
quickSort(arr, low, partPoint - 1);
//递归右边
quickSort(arr, partPoint + 1, high);
}
//进行一次左右换位
public static int partition(int[] arr, int low, int high) {
int leader = arr[low];
while (low < high) {
while (low < high && arr[high] >= leader) {
//从右边寻找第一个小于leader的数字
high--;
}
// 交换值
arr[low] = arr[high];
while (low < high && arr[low] <= leader) {
//从左边找到第一个大于leader的数字
low++;
}
arr[high] = arr[low];
}
arr[low] = leader;
return low;
}
}
效率版
思路和标准版一致
//速度优化之后的快速排序
public static void optimizeQuickSort(int[] arr, int low, int high) {
int l = low;
int r = high;
int pivot = arr[l + r / 2];
int temp = 0;
while (l < r) {
while (arr[l] < pivot) {
l += 1;
}
while (arr[r] > pivot) {
r -= 1;
}
if (l >= r) {
break;
}
temp = arr[l];
arr[l] = arr[r];
arr[r] = temp;
if (arr[l] == pivot) {
r -= 1;
}
if (arr[r] == pivot) {
l += 1;
}
}
//防止栈溢出
if (l == r) {
l += 1;
r -= 1;
}
//防止栈溢出,当low指针0 r = 0 的时候就不许要排序递归左边了,
if (low < r) {
quickSort(arr, low, r);
}
//当 高位大于 左边指针的时候 就需要向右边递归了
if (high > l) {
quickSort(arr, l, high);
}
}
分类:
无
标签:
算法 | 排序算法 | 快速排序