1.快速排序的基本思想
快速排序是对起泡排序的一种改进,它的基本思想是:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,分别对这两部分记录继续排序,已达到整个序列有序。
2.将数组s快速排序的递归算法
(1)如果s中元素个数是0或1,则返回
(2)取s中任一元素v,称之为枢纽元
(3)将s - {v}划分成两个不相交的集合:s1 = {x <= v}和s2={x>=v}
(4)返回{quicksort(s1)}后跟v,继而返回{quicksort(s2)}
3.选取枢纽元
(1)一种错误的方法是将第一个元素用作枢纽元,原因:如果输入是预排序的或是反序的,这样的枢纽元就产生一个劣质的分割,因为所有的元素不是都被划入s1就是被划入s2。
(2)安全的做法:随机选取枢纽元
(3)三数中值分割法:一般做法是使用左端,右端和中心位置上的三个元素的中值作为枢纽元。
4.分割策略
(1)通过将枢纽元与最后的元素交换使得枢纽元离开要被分割的数据段。i从第一个元素开始而j从倒数第二个元素开始。
把所有比枢纽元小的元素移到数组的左边而把比枢纽元大的元素移到数组的右边。
(2)当i在j的左边时,我们将i右移,移过那些小于枢纽元的元素,并将j左移,移过那些大于枢纽元的元素。当i和j停止时,i指向一个大于枢纽元的元素而j指向一个小于枢纽元的元素。如果i在j的左边,那么将这两个元素互换。
(3)若i和j已经交错,故不再交换。分割的最后一步是将枢纽元与i所指向的元素交换。
注:当i和j遇到等于枢纽元的关键字,就让i和j都停止
5.代码如下
package com.mfl;
public class TestKuaiPai {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] a = { 13,81,92,43,31,65,57,26,75,0,8,1,4,9,6,3,5,2,7,0,84,99};
KuaiPai.quicksort(a, 0, a.length - 1);
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
}
}
class KuaiPai {
public static void swap(int[] a, int i, int j) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
/**
* 此方法将三元素中的最小者被分在a[left] 三元素中的最大者被分在a[right] 枢纽元放在a[right-1]
*
* @param a
* @param left
* @param right
* @return
*/
public static int median(int[] a, int left, int right) {
int center = (left + right) / 2;
if (a[center] < a[left]) {
swap(a, left, center);
}
if (a[right] < a[left]) {
swap(a, left, right);
}
if (a[right] < a[center]) {
swap(a, right, center);
}
swap(a, center, right - 1);
return a[right - 1];
}
public static void quicksort(int[] a, int left, int right) {
if(right - left >=2) {
int pivot = median(a, left, right);
int i = left + 1;
int j = right - 2;
for (;;) {
while (a[i] < pivot) {
i++;
}
while (a[j] > pivot) {
j--;
}
if (i < j) {
swap(a, i, j);
} else
break;
}
swap(a, i, right - 1);
quicksort(a, left, i - 1);
quicksort(a, i + 1, right);
}else if(right - left == 1) {
if(a[left] > a[right]) {
int tmp = a[left];
a[left] = a[right];
a[right] = tmp;
}
}else return;
}
}