java实现快速排序:
一:先来一个常规快排:
这个方式就是我们的基准值一直在两个边界徘徊,要么在less的较大边界,要么是在more的小边界,其实就是在居中位置徘徊。
package chapter1;
//来一个快排,常规快排
public class QuickSort {
public static void main(String[] args) {
int[] arr = { 1, 2, 7, 5, 4, 3, 9, 2, 7 };
System.out.print("排序前 ");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
System.out.println();
quickSort(arr, 0, arr.length-1);
System.out.print("排序后 ");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
}
public static void quickSort(int[] arr, int low, int high) {
if (low < high) {
int patition = patition(arr, low, high);
quickSort(arr, low, patition-1);
quickSort(arr, patition + 1, high);
}
}
public static int patition(int[] arr, int low, int high) {
int num = arr[low];// 我们取第一个作为基准值,而且基准值开始是在最低位
while (low < high) {
while (low < high && arr[high] > num) {
high--;
}
swap(arr, low, high);//交换后,基准值跑到高位较小的位置了
while (low < high && arr[low] <= num) {
low++;
}
swap(arr, low, high);//交换后,基准值又跑到低位较大位置了
}
return low;
}
private static void swap(int[] arr, int low, int high) {
int temp = arr[low];
arr[low] = arr[high];
arr[high] = temp;
}
}
控制台打印如下:
改进版本:就是添加了排除相等部分的重复排序:
package chapter1;
//来一个快排,改进快排,我们多添加一个记录想等值。
public class QuickSort {
public static void main(String[] args) {
int[] arr = { 1, 2, 7, 5, 4, 3, 9, 2, 7 };
System.out.print("排序前 ");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
quickSort(arr, 0, arr.length - 1);
System.out.print("排序后 ");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
public static void quickSort(int[] arr, int low, int high) {
if (low < high) {
int[] patition = patition(arr, low, high);
quickSort(arr, low, patition[0] - patition[1]);
quickSort(arr, patition[0] + 1, high);
}
}
public static int[] patition(int[] arr, int low, int high) {
int num = arr[low];// 我们取第一个作为基准值
int equal = 0;// 这个用来记录等于基准值的数量,至少是1
int result[] = new int[2];
while (low < high) {
while (low < high && arr[high] > num) {
high--;
}
swap(arr, low, high);
while (low < high && arr[low] <= num) {
if (arr[low] == num) {
equal++;
}
low++;
}
swap(arr, low, high);
}
result[0] = low;
result[1] = equal;
return result;
}
private static void swap(int[] arr, int low, int high) {
int temp = arr[low];
arr[low] = arr[high];
arr[high] = temp;
}
}
控制台:
二:左程云方式的快排
其实就是多了一部分,多了指出相等值的那部分,第二次就不需要再去重复排那些相等值的过程
首先来看一个问题:我们快排第一步是找一个基准值 ,然后右边值都大于基准值,左边值都小于基准值。
题目一:我随意给定一个数组和一个给定值,大于该值放右边,其他放左边,同时不能使用多余数组
package chapter1;
//需求:给一个数组,和其中一个数,将大于这个数和小于这个数的分成两边
public class GroupTest {
public static void main(String[] args) {
int[] arr = { 1, 2, 7, 5, 4, 3, 9, 2, 7 };
int num = 6;
group(arr, num);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]);
}
}
public static void group(int[] arr, int num) {
int p = 0;
int small = 0;// 小数的边界
int big = arr.length - 1;// 大数的边界
while (small < big) {
if (arr[p] < num) {
exchange(arr, small, p);
small++;
p++;
} else {
exchange(arr, big, p);
big--;
}
}
}
private static void exchange(int[] arr, int q, int p) {
// TODO Auto-generated method stub
int temp = arr[p];
arr[p] = arr[q];
arr[q] = temp;
}
}
控制台:
通常我们选取最后一个或者第一个值为我们的基准值。下边我们选取最后一个值作为基准值,而且如果我们使用了把中间值拿过来放着后边不做比较,那么我们比较次数会更少一点
题目二:给定一个整型数组,然后以最后一个数为基准,将大于基准值的放右边,小于基准值放到左边。最后数组的情况就是,在基准值两边,一边是全部大于基准值,一边是全部小于基准值;
我们使用三个指针来区分三块,一块是小于区域,中间是等于区域,右边是大于区域。开始的时候,小于和大于区域都是在数组外边,要是存在一个符合要求的,就放到相应区域,同时该区域长度就增加1。如果是有一个小于的,首先交换当前值和less后边那个值,那么小于的区域的指针就++less,同时也会推着中间部分往右边跑,所以当前指针cur++;如果是满足大于区域,就把当前cur指向的数和大于那边的区域的边界more前边的那个数值交换,同时大于区域增加,就是--more,但是这里我们的cur就不变化。
代码:
package test2018926;
public class QuickSort {
public static void main(String[] args) {
Integer[] arr = { 1, 2, 7, 5, 4, 3 };
partition(arr, 0, arr.length - 1);
}
public static Integer[] partition(Integer[] arr, int L, int R) {
// 使用三个指针来将我们的数据分成三类,
int cur = L;// 这个指向当前数据
int less = L - 1;// 小数的前面一个
int more = R + 1;// 大数的后边一个
int num = arr[arr.length - 1];// 以最后一个值为基准来排出大于和小于
Integer[] arr1 = new Integer[2];
while (cur < more) {
// System.out.println(cur);
if (arr[cur] > num) {
swap(arr, cur, --more);
} else if (arr[cur] < num) {
swap(arr, cur++, ++less);// less位置增加一个,就会推着cur向后
} else {
cur++;
}
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]);
}
arr1[0] = less + 1;//等于num的左边界
arr1[1] = more - 1;//等于num的右边界
return arr1;
}
// 交换数组位置
private static void swap(Integer[] arr, Integer m, Integer n) {
int temp = arr[m];
arr[m] = arr[n];
arr[n] = temp;
}
}
控制台打印:
题目三:下边讲解我们的改进快排:
快排就是不断细分,对一个小部分都进行上边相同的操作。
开始分为两边,然后对两边分别再分两边,一直分到最小,就是分成单个为止。
package test2018926;
public class QuickSort {
public static void main(String[] args) {
Integer[] arr = { 1, 2, 7, 5, 4, 3 };
quickSort(arr, 0, arr.length - 1);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]);
}
}
public static void quickSort(Integer[] arr, int L, int R) {
if (L < R) {
Integer[] p = partition(arr, L, R);// 返回的是相同数值区域的两个边界
quickSort(arr, L, p[0] - 1);//p[0]是等于部分的左边界
quickSort(arr, p[1] + 1, R);//p[1]是等于部分的右边界
}
}
public static Integer[] partition(Integer[] arr, int L, int R) {
// 使用三个指针来将我们的数据分成三类,
int cur = L;// 这个指向当前数据
int less = L - 1;// 小数的前面一个
int more = R + 1;// 大数的后边一个
int num = arr[arr.length - 1];// 以最后一个值为基准来排出大于和小于
Integer[] arr1 = new Integer[2];
while (cur < more) {
// System.out.println(cur);
if (arr[cur] > num) {
swap(arr, cur, --more);
} else if (arr[cur] < num) {
swap(arr, cur++, ++less);// less位置增加一个,就会推着cur向后
} else {
cur++;
}
}
for (int i = 0; i < arr.length; i++) {
// System.out.print(arr[i]);
}
arr1[0] = less + 1;
arr1[1] = more - 1;
return arr1;
}
// 交换数组位置
private static void swap(Integer[] arr, Integer m, Integer n) {
int temp = arr[m];
arr[m] = arr[n];
arr[n] = temp;
}
}
控制台打印: