定义
百科中的快速排序的介绍是:
快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
实现思路
从数据中选择一个基准数,将整个数据中比基准数小的放到基准数的左边,比基准数大的数放到右边。这样整个数据就分成了两个部分,再将两个部分的数据通过递归在执行前面的操作,重复即可完成排序。
整个算法中基准数的选择绝定了算法的效率一般有三种方式。
1》将数据中的第一个数作为基准数,在随机的数据中效率还行,但在反序的数据中效率低下。
2》随机选择一个数为基准数,因为每次都要随机产生基准数效率有所降低。
3》三数中值分割法,一组N个数的中值是第[N/2]个最大的数。”基准“的最好选择是数组的中值。但是这很难算出,且减慢快速排序的速度。这样的中值的估计量可以通过随机选取三个元素并用它们的中值作为”基准”而得到。实际上,随机性并没有多大的帮助,因此一般的做法是使用左端、右端和中心位置上的三个元素的中值作为“基准”。
下面以 4 6 2 8 5 9 1 为例子讲解.
1.选择基准(此处选择每个部分的第一个为基准。)这里选择4作为基准。
2.从右边开始找比基准数4小的数1,找到后记录数据下标j=6,再从左边向右找比基准数4大的数6,记录下标i=1.将1和6交换。交换后的数据为:4 1 2 8 5 9 6.继续从右向左找,找到2比4小,记录其下标j=2,再从左往右找比基准数大的数,再找到之前碰到了j,停止寻找。将相遇的下标记下为i=j=2;将下标为2的数据与基准数交换,得到新数据为:2 1 4 8 5 9 6.这样就结束了一次查找。将数据分为两部分,基准数左边的都是比基准数小的。2 1;基准数的右边都是比基准数大的数:8 5 9 6。
3使用递归将两个数据,重复执行上述步骤,直到所有分出的数据长度小于等于1,快速排序就写好了。
代码实现
:
package sort;
import java.util.Random;
public class Quicksort{
/**
* main方法
* @param args
*/
public static void main(String[] args) {
//定义数组
int A[] = new int[100];
//给数组赋值
for (int i = 0;i<100;i++)
{
A[i]=i;
}
//创建一个随机数对象,用于随机打乱数组顺序
Random rand = new Random();
//打乱数组
for(int i=0;i<100;i++)
{
//随机两个下标,将其值交换
int x = rand.nextInt(100);
int y = rand.nextInt(100);
int t = A[x];
A[x] = A[y];
A[y]= t;
}
System.out.println("初始数据为:");
for(int i = 0 ;i<A.length;i++) //输出初始数组
System.out.print(" "+A[i]);
System.out.println();
long begin = System.nanoTime(); //记录初始时间
quicksort(A,0,A.length-1); //快速排序
//sortA(A); // 冒泡排序
long end = System.nanoTime(); // 记录排序完结束时间
for(int i = 0 ;i<A.length;i++) // 输出数组
System.out.print(" "+A[i]);
System.out.println();
System.out.println("排序用的时间为: "+(end-begin)+"ns");//输出排序用的时间
}
/**
* 快速排序方法
* @param a 排序的数组
* @param start 开始第一个数据的下标
* @param end 最后一个数据的下标
*/
public static void quicksort(int[] a,int start,int end)
{
if(start>=end) // 如果start大于等于end,结束递归
return;
int m = start;//将数据的第一个数作为基准数,m为下标
int i=start,j=end; // 给i,j赋初值
int key=a[m]; // key作为基准数据
while (i!=j) //如果i和j没有碰到,执行下面步骤
{
while (a[j]>=key && i!=j){ //从右边开始找比基准数小的数据,大的话j--
j--;
}
while (a[i]<=key && i!=j) { //从左边开始找比基准数大的数据,小的话i++
i++;
}
if(i!=j){ //如果i和j没有相遇那么交换下标为i,j的值
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
int x = a[m]; //交换基准数和i,j相遇的下标的值
a[m] = a[i];
a[i] = x;
quicksort(a,start,j-1); //使用递归继续将基准数左边的数据排序
quicksort(a,j+1,end);//使用递归继续将基准数右边的数据排序
}
/**
* 选择排序
* @param a 需要排序的数组
*/
public static void sortA(int a[]){
for(int i = 0;i<a.length;i++){
for (int j=i+1;j<a.length;j++)
if(a[j]<a[i]){
int temp = a[j];
a[j] = a[i];
a[i] = temp;
}
}
}
}
选择排序用的时间
快速排序用的时间