Java实现快速排序算法
算法思路:
快速排序是基于分治法的思想
利用三数中值分割法寻找支点,并将支点左侧的元素全部小于支点元素,支点右侧的元素全部大于支点元素,然后将此数组分为三个部分,支点,支点左边子数组和支点右边子数组。然后不断的对左右两部分进行此方法,一直到子数组的长度小于3,退出递归程序后即为排序好的数组
寻找支点的方法:
将数组的最左边和最右边和中间的元素进行由小到大的排序,并取中间元素的值作为支点,保证a[left]<pivot<a[right],并将此支点移动到最右边元素的左边。
分割的方法:
定义i和j,分别指向左右两边,将i从左向右移动,一直移动到大于支点的元素的位置,将j从右向左移动,一直移动到小于支点的元素的位置,如果此时i < j,则将i和j对应位置元素互换,重复此方法,一直到i > j,最后将i对应的元素和支点元素互换,这样就确保了支点元素的左边均小于支点元素,而支点元素的右边均大于支点元素。
Java代码实现:
public class QuickSort {
public static void main(String[] args) {
int[] a = {90, 90,67, 3, 8, 43, 89, 90, 90};
System.out.print("原数组为:");
for (int i = 0; i < a.length; i++) {
System.out.print(a[i]+",");
}
System.out.println();
quickSort(a, 0, a.length - 1);
System.out.print("快速排序后的数组为:");
for (int i = 0; i < a.length; i++) {
System.out.print(a[i]+",");
}
}
private static void quickSort(int[] a, int left, int right) {
//递归出口,如果子数组长度小于3,则return
if (right - left <= 1) return;
//利用三数中值法找到支点
int pivot = findPivot(a, left, right);
int i = left;
int j = right - 1;
for (; ; ) {
//使用a[++i]和a[--j]此方法为了防止当数组中的元素全相同时陷入死循环
while (a[++i] < pivot) {
}
while (a[--j] > pivot) {
}
if (i < j) {
swap(a, i, j);
} else {
break;
}
}
//将pivot对应的数组元素与i交换,使得pivot的左边是小元素,右边是大元素
swap(a, i, right - 1);
//对支点左边的子数组和支点右边的子数组进行排序
quickSort(a, left, i - 1);
quickSort(a, i + 1, right);
}
private static void swap(int[] a, int i, int j) {
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
// 寻找支点的方法,将两个端点和中间位置的三个元素的中间元素值作为支点
// 顺便让left小于支点元素小于right,可以减少一次比较次数
private static int findPivot(int[] a, int left, int right) {
int mid = (left + right) / 2;
if (a[left] > a[mid]) {
swap(a, left, mid);
}
if (a[right] < a[mid]) {
swap(a, right, mid);
}
if (a[left] > a[right]) {
swap(a, left, right);
}
//将支点元素移动到最右边元素的左边,这样可以减少一次比较次数
swap(a, mid, right - 1);
return a[right - 1];
}
}