详解Java中使用泛型实现快速排序算法的方法
快速排序算法概念
快速排序一般基于递归实现。其思路是这样的:
1.选定一个合适的值(理想情况中值最好,但实现中一般使用数组第一个值),称为“枢轴”(pivot)。
2.基于这个值,将数组分为两部分,较小的分在左边,较大的分在右边。
3.可以肯定,如此一轮下来,这个枢轴的位置一定在最终位置上。
4.对两个子数组分别重复上述过程,直到每个数组只有一个元素。
5.排序完成。
基本实现方式:
publicstaticvoidquickSort(int[]arr){ qsort(arr,0,arr.length-1); } privatestaticvoidqsort(int[]arr,intlow,inthigh){ if(low<high){ intpivot=partition(arr,low,high);//将数组分为两部分 qsort(arr,low,pivot-1);//递归排序左子数组 qsort(arr,pivot+1,high);//递归排序右子数组 } } privatestaticintpartition(int[]arr,intlow,inthigh){ intpivot=arr[low];//枢轴记录 while(low<high){ while(low<high&&arr[high]>=pivot)--high; arr[low]=arr[high];//交换比枢轴小的记录到左端 while(low<high&&arr[low]<=pivot)++low; arr[high]=arr[low];//交换比枢轴小的记录到右端 } //扫描完成,枢轴到位 arr[low]=pivot; //返回的是枢轴的位置 returnlow; }
使用泛型实现快排算法
下面设计一个QuickSort类,包含了静态函数sort(),可以对任意类型数组进行排序。如果为对象类型数组,则该对象类型必须实现Comparable接口,这样才能使用compareTo函数进行比较。
使用了最基本的快排算法,没有进行优化处理。
源代码如下:
importjava.util.LinkedList; importjava.util.List; importjava.util.ListIterator; importjava.util.Random; publicclassQuickSort{ @SuppressWarnings("unchecked") //对上述快排函数原型修改,使其可以对任意对象类型数组进行排序。这个函数为内部使用,外部排序函数接口为sort(),sort函数要求对象必须实现Comparable接口,可以提供编译时类型检测,见后文。 privatestaticvoidquickSort(Object[]in,intbegin,intend){ if(begin==end||begin==(end-1))return; Objectp=in[begin]; inta=begin+1; intb=a; for(;b<end;b++){ //该对象类型数组必须实现Comparable接口,这样才能使用compareTo函数进行比较 if(((Comparable<Object>)in[b]).compareTo(p)<0){ if(a==b){a++;continue;} Objecttemp=in[a]; in[a]=in[b]; in[b]=temp; a++; } } in[begin]=in[a-1]; in[a-1]=p; if(a-1>begin){ quickSort(in,begin,a); } if(end-1>a){ quickSort(in,a,end); } return; } //使用泛型,对任意对象数组排序,该对象类型数组必须实现Comparable接口 publicstatic<TextendsComparable<?superT>>voidsort(T[]input){ quickSort(input,0,input.length); } //添加对List对象进行排序的功能,参考了Java中的Java.util.Collections类的sort()函数 publicstatic<TextendsComparable<?superT>>voidsort(List<T>list){ Object[]t=list.toArray();//将列表转换为数组 quickSort(t,0,t.length);//对数组进行排序 //数组排序完成后再写回到列表中 ListIterator<T>i=list.listIterator(); for(intj=0;j<t.length;j++){ i.next(); i.set((T)t[j]); } } //由于Java中原始数据类型(int、double、byte等)无法使用泛型,所以只能使用函数重载机制实现对这些原始类型数组(int[]、double[]、byte[]等)的排序。这里为了共用同一个排序函数,利用原始类型的(AutoBoxing,UnBoxing)机制将其封装为对应对象类型,组成新的对象数组,排序后再解封装,这样的缺点是需要额外的转换步骤、额外的空间保存封装后的数组。另一种方式是将排序代码复制到各个重载函数中,官方API中的Java.util.Arrays这个类中的sort()函数就是使用这种方法,可以从Arrays类的源代码看出。 publicstaticvoidsort(int[]input){ Integer[]t=newInteger[input.length]; for(inti=0;i<input.length;i++){ t[i]=input[i];//封装 } quickSort(t,0,t.length);//排序 for(inti=0;i<input.length;i++){ input[i]=t[i];//解封装 } } //double[]数组的重载函数 publicstaticvoidsort(double[]input){ Double[]t=newDouble[input.length]; for(inti=0;i<input.length;i++){ t[i]=input[i]; } quickSort(t,0,t.length); for(inti=0;i<input.length;i++){ input[i]=t[i]; } } //byte[]数组的重载函数 publicstaticvoidsort(byte[]input){ Byte[]t=newByte[input.length]; for(inti=0;i<input.length;i++){ t[i]=input[i]; } quickSort(t,0,t.length); for(inti=0;i<input.length;i++){ input[i]=t[i]; } } //short[]数组的重载函数 publicstaticvoidsort(short[]input){ Short[]t=newShort[input.length]; for(inti=0;i<input.length;i++){ t[i]=input[i]; } quickSort(t,0,t.length); for(inti=0;i<input.length;i++){ input[i]=t[i]; } } //char[]数组的重载函数 publicstaticvoidsort(char[]input){ Character[]t=newCharacter[input.length]; for(inti=0;i<input.length;i++){ t[i]=input[i]; } quickSort(t,0,t.length); for(inti=0;i<input.length;i++){ input[i]=t[i]; } } //float[]数组的重载函数 publicstaticvoidsort(float[]input){ Float[]t=newFloat[input.length]; for(inti=0;i<input.length;i++){ t[i]=input[i]; } quickSort(t,0,t.length); for(inti=0;i<input.length;i++){ input[i]=t[i]; } } //测试用的main函数 publicstaticvoidmain(String[]args){ //生产一个随机数组成的int[]数组,用来测试 intLEN=10; int[]input=newint[LEN]; Randomr=newRandom(); System.out.print("int[]beforesorting:"); for(inti=0;i<input.length;i++){ input[i]=r.nextInt(10*LEN); System.out.print(input[i]+""); } System.out.println(); System.out.print("int[]aftersorting:"); sort(input); for(inti:input){ System.out.print(i+""); } System.out.println(); //生成一个字符串数组,用来测试 String[]s=newString[]{"b","a","e","d","f","c"}; System.out.print("String[]beforesorting:"); for(inti=0;i<s.length;i++){ System.out.print(s[i]+""); } System.out.println(); System.out.print("String[]aftersorting:"); sort(s); for(inti=0;i<s.length;i++){ System.out.print(s[i]+""); } System.out.println(); //生成一个字符串列表,用来测试 List<String>l=newLinkedList<String>(); s=newString[]{"b","a","e","d","f","c"}; System.out.print("LinkedList<String>beforesorting:"); for(intj=0;j<s.length;j++){ l.add(s[j]); System.out.print(s[j]+""); } System.out.println(); sort(l); System.out.print("LinkedList<String>aftersorting:"); for(Stringts:l){ System.out.print(ts+""); } System.out.println(); } }
运行main函数测试,从输出可以看出QuickSort类工作正常:
int[]beforesorting:654892263859211645 int[]aftersorting:381621264548596592 String[]beforesorting:baedfc String[]aftersorting:abcdef LinkedList<String>beforesorting:baedfc LinkedList<String>aftersorting:abcdef