简单快速排序
选取数组第一个元素为临界值,然后将数组排序,小于临界值得都放在临界值左边,大于临界值的都放在临界值右边,然后递归知道数组完全有序.但是如果数组基本有序或者数组中重复元素较多的情况下,临界值的依然选择第一个就不是很恰当了,所以后续会有快排的优化
/**
* 简单快速排序--对于基本有序的数组和重复元素较多的数组时间复杂度较高,存在不足需要改进
*/
public class QuickSort {
private QuickSort() {
}
//通过分区,返回两个区的临界值
private static <T extends Comparable<? super T>> int partition(T[] arr, int low, int high) {
T temp = arr[low];
int j = low;
for (int i = low + 1; i <= high; i++) {
if (arr[i].compareTo(temp) < 0) {
j++;
swap(arr, i, j);
}
}
swap(arr, low, j);
return j;
}
//递归将数组分区
private static <T extends Comparable<? super T>> void sort(T[] arr, int low, int high) {
if (low >= high) {
return;
}
int partition = partition(arr, low, high);
sort(arr, low, partition - 1);
sort(arr, partition + 1, high);
}
public static <T extends Comparable<? super T>> void sort(T[] arr) {
sort(arr, 0, arr.length - 1);
}
//交换数组中的两个元素
private static <T extends Comparable<? super T>> void swap(T[] arr, int i, int j) {
T temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
//打印数组元素
public static <T extends Comparable<? super T>> void printArray(T[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
public static void main(String[] args) {
Integer[] arr = {9, 5, 1, 3, 7, 2, 8, 4, 6, 10};
sort(arr);
printArray(arr);
}
}
快速排序优化
优化一:如果基本有序数组的第一个元素是临界值,那么临界值很可能是最小的元素,导致分区不均,时间复杂度相当于O(n^2),所以为了尽量消除数组基本有序的情况,在数组中随机选取一个元素,解决了数组基本有序排序效率低的情况,但是若数组中存在大量重复元素,效率低的情况仍未解决.
优化二:对于数组中元素基本有序时,可以更换为直接插入排序,提高排序效率
public class QuickSort {
private QuickSort() {
}
//通过分区,返回两个区的临界值
private static <T extends Comparable<? super T>> int partition(T[] arr, int low, int high) {
/*优化一:随机选取数组中的一个元素,将其与数组第一个元素进行交换*/
swap(arr, low, (int) (Math.random() * (high - low + 1) + low));
T temp = arr[low];
int j = low;
for (int i = low + 1; i <= high; i++) {
if (arr[i].compareTo(temp) < 0) {
j++;
swap(arr, i, j);
}
}
swap(arr, low, j);
return j;
}
//递归将数组分区
private static <T extends Comparable<? super T>> void sort(T[] arr, int low, int high) {
/*优化二:对于基本有序的数组可以使用直接插入排序*/
if (high - low <= 15) {
insertionSort(arr, low, high);
return;
}
int partition = partition(arr, low, high);
sort(arr, low, partition - 1);
sort(arr, partition + 1, high);
}
public static <T extends Comparable<? super T>> void sort(T[] arr) {
sort(arr, 0, arr.length - 1);
}
// 对arr[l...r]的区间使用InsertionSort排序
public static void insertionSort(Comparable[] arr, int l, int r) {
for (int i = l + 1; i <= r; i++) {
Comparable temp = arr[i];
int j = i;
for (; j > l && arr[j - 1].compareTo(temp) > 0; j--)
arr[j] = arr[j - 1];
arr[j] = temp;
}
}
//交换数组中的两个元素
private static <T extends Comparable<? super T>> void swap(T[] arr, int i, int j) {
T temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
//打印数组元素
public static <T extends Comparable<? super T>> void printArray(T[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
public static void main(String[] args) {
Integer[] arr = {9, 5, 1, 3, 7, 2, 8, 4, 6, 10};
sort(arr);
printArray(arr);
}
}
快速排序--优化2
从左向右找比临界值大的,从右向左找比临界值小的,然后将两者交换,这样对于大量相同的元素不用全部交换,解决了数组中存在大量元素的问题
public class QuickSort {
private QuickSort() {
}
//通过分区,返回两个区的临界值
private static <T extends Comparable<? super T>> int partition(T[] arr, int low, int high) {
/*优化:随机选取数组中的一个元素,将其与数组第一个元素进行交换*/
swap(arr, low, (int) (Math.random() * (high - low + 1) + low));
T temp = arr[low];
int i = low + 1;
int j = high;
while (true) {
while (i <= high && arr[i].compareTo(temp) < 0) {
i++;
}
while (j >= low + 1 && arr[j].compareTo(temp) > 0) {
j--;
}
if (i > j) {
break;
}
swap(arr,i,j);
i++;
j--;
}
swap(arr, low, j);
return j;
}
//递归将数组分区
private static <T extends Comparable<? super T>> void sort(T[] arr, int low, int high) {
/*对于基本有序的数组可以使用直接插入排序*/
if (high - low <= 15) {
insertionSort(arr, low, high);
return;
}
int partition = partition(arr, low, high);
sort(arr, low, partition - 1);
sort(arr, partition + 1, high);
}
public static <T extends Comparable<? super T>> void sort(T[] arr) {
sort(arr, 0, arr.length - 1);
}
// 对arr[l...r]的区间使用InsertionSort排序
public static void insertionSort(Comparable[] arr, int l, int r) {
for (int i = l + 1; i <= r; i++) {
Comparable temp = arr[i];
int j = i;
for (; j > l && arr[j - 1].compareTo(temp) > 0; j--)
arr[j] = arr[j - 1];
arr[j] = temp;
}
}
//交换数组中的两个元素
private static <T extends Comparable<? super T>> void swap(T[] arr, int i, int j) {
T temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
//打印数组元素
public static <T extends Comparable<? super T>> void printArray(T[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
public static void main(String[] args) {
Integer[] arr = {9, 5, 1, 3,7, 7, 2, 8, 4, 6, 10};
sort(arr);
printArray(arr);
}
}
两路快排--不交换
public class QuickSort {
private QuickSort() {
}
//通过分区,返回两个区的临界值
private static <T extends Comparable<? super T>> int partition(T[] arr, int low, int high) {
/*优化:随机选取数组中的一个元素,将其与数组第一个元素进行交换*/
swap(arr, low, (int) (Math.random() * (high - low + 1) + low));
T temp = arr[low];
int i = low + 1;
int j = high;
while (i < j) {
while (i < j && temp.compareTo(arr[j]) < 0) {
j--;
}
arr[i] = arr[j]; //j停在那里不动
while (i < j && temp.compareTo(arr[j]) > 0) {
i++;
}
arr[j] = arr[i];//i停在那里不动
}
arr[j] = temp;
return j;
}
//递归将数组分区
private static <T extends Comparable<? super T>> void sort(T[] arr, int low, int high) {
/*对于基本有序的数组可以使用直接插入排序*/
if (high - low <= 15) {
insertionSort(arr, low, high);
return;
}
int partition = partition(arr, low, high);
sort(arr, low, partition - 1);
sort(arr, partition + 1, high);
}
public static <T extends Comparable<? super T>> void sort(T[] arr) {
sort(arr, 0, arr.length - 1);
}
// 对arr[l...r]的区间使用InsertionSort排序
public static void insertionSort(Comparable[] arr, int l, int r) {
for (int i = l + 1; i <= r; i++) {
Comparable temp = arr[i];
int j = i;
for (; j > l && arr[j - 1].compareTo(temp) > 0; j--)
arr[j] = arr[j - 1];
arr[j] = temp;
}
}
//交换数组中的两个元素
private static <T extends Comparable<? super T>> void swap(T[] arr, int i, int j) {
T temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
//打印数组元素
public static <T extends Comparable<? super T>> void printArray(T[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
public static void main(String[] args) {
Integer[] arr = {9, 5, 1, 3, 7, 7, 2, 8, 4, 6, 10};
sort(arr);
printArray(arr);
}
}
三路快排
public class QuickSort {
private QuickSort() {
}
private static <T extends Comparable<? super T>> int[] partition(T[] arr, int low, int high) {
swap(arr, low, (int) (Math.random() * (high - low + 1) + low));
T temp = arr[low];
int i = low;
int j = high;
int cur = i;
while (cur <= j) {
if (temp.compareTo(arr[cur]) == 0) {
cur++;
} else if (temp.compareTo(arr[cur]) > 0) {
swap(arr, cur++, i++);
} else {
swap(arr, cur, j--);
}
}
return new int[]{i - 1, j + 1};
}
private static <T extends Comparable<? super T>> void sort(T[] arr, int low, int high) {
if (high - low <= 15) {
insertionSort(arr, low, high);
return;
}
int[] ret = partition(arr, low, high);
sort(arr, low, ret[0]);
sort(arr, ret[1], high);
}
public static <T extends Comparable<? super T>> void sort(T[] arr) {
sort(arr, 0, arr.length - 1);
}
// 对arr[l...r]的区间使用InsertionSort排序
private static void insertionSort(Comparable[] arr, int l, int r) {
for (int i = l + 1; i <= r; i++) {
Comparable temp = arr[i];
int j = i;
for (; j > l && arr[j - 1].compareTo(temp) > 0; j--)
arr[j] = arr[j - 1];
arr[j] = temp;
}
}
//交换数组中的两个元素
private static <T extends Comparable<? super T>> void swap(T[] arr, int i, int j) {
T temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
//打印数组元素
public static <T extends Comparable<? super T>> void printArray(T[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
public static void main(String[] args) {
Integer[] arr = {9, 5, 1, 3, 7, 7, 2, 8, 4, 6, 10};
sort(arr);
printArray(arr);
}
}