单边循环快速排序(lomuto分区方案)
核心思想:每轮找到一个基准点元素,把比它小的放到它左边,比它大的放到它右边,这称为分区
1. 选择最右元素作为基准点元素
2. j指针负责找到比基准点小的元素,i指针指责找到比基准点小的元素,一旦找到则与i进行交换
3. 最后基准点与i交换,i即为分区位置
方法:
public static void sort(int[] a) {
quick(a, 0, a.length - 1);
}
private static void quick(int[] a, int left, int rigth) {
if (left >= rigth) {
return;
}
int p = partition(a, left, rigth); //p代表基准点元素的索引
quick(a, left, p - 1);
quick(a, p + 1, rigth);
}
private static int partition(int[] a, int left, int rigth) {
//先找到基准点元素值(最右侧)
int pv = a[rigth];//基准点
int i = left; //i 找大于基准点的
int j = rigth;//j 找小于基准点的
while (j < rigth) {
if (a[j] < pv) { //j找到比基准点小的了
if (i != j) { //i,j不等时才进行交换
swap(a, i, j);
}
i++;//j找到比基准点小的了,i继续找,所以i++写在if里面
}
j++;
}
swap(a, i, rigth);
return i;
}
//交换的方法
private static void swap(int[] a ,int i, int j) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
双边循环快速排序
核心思想:
1. 选择左侧元素作为基准点
2. j找比基准点小的,i找比基准点大的,一旦找到,二者进行交换
i从左向右,j从右向左
3. 最后基准点与i交换,i即为基准点最终索引
方法名
public static void quicksort(int[] a, int left, int right) {}
1. 准备变量
if (left > right) {
return;
}
int i = left;
int j = right;
int pv = a[left];
i在最左侧,j在最右侧,pv是基准点,默认在最左侧
2. i和j分别寻找符合条件的值,并进行交换
while (i < j) {
while (i < j && a[j] > pv) {
j--;
}
while (i < j && a[i] <= pv) {
i++;
}
if (i < j) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
3. 更改左边界,确定最终基准点
a[left] = a[i];
a[i] = pv;
4. 进行递归
quicksort(a, left, j - 1);
quicksort(a, j + 1, right);
对基准点左侧和右侧数组分别进行双边快速排序