排序算法API
返回值 |
名称(参数) |
作用 |
void |
sort(Comparable[] a) |
对传入的数据数组进行排序 |
boolean |
less(Comparable v,Comparable w) |
比较两个可比较数据类习惯的数据,返回比较结果布尔值 |
void |
exch(Comparable[] a,int i,int j) |
交换索引为i和j的数据 |
void |
show(Comparable[] a) |
打印数组 |
boolean |
isSorted(Comparable[] a) |
判断是否经过排序 |
选择排序
选择排序的过程就是不断从数组中找出最小值的过程,首先,遍历整个数组找到最小值,将它与首个元素交换,然后,遍历剩余数组,找到此时最小值,与第二位交换。如此往复,经过N轮,获得排好序的数组
package cn.ywrby.sorts;
import cn.ywrby.tools.StopWatch;
import java.util.Random;
public class SelectionSort {
public static void sort(Comparable[] a) {
for(int i=0;i<a.length;i++){
int min=i;
for(int j=i+1;j<a.length;j++){
if(less(a[j],a[min])) {
min = j;
}
}
exch(a,i,min);
}
}
private static boolean less(Comparable v, Comparable w) {
return v.compareTo(w) < 0;
}
private static void exch(Comparable[] a, int i, int j) {
Comparable temp = a[i];
a[i] = a[j];
a[j] = temp;
}
private static void show(Comparable[] a) {
System.out.print("After sort : ");
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
System.out.println();
}
public static boolean isSorted(Comparable[] a) {
for (int i = 0; i < a.length-1; i++) {
if (!less(a[i],a[i+1])){return false;}
}
return true;
}
public static void main(String[] args){
int N=200;
Comparable<Double>[] test=new Comparable[N];
System.out.print("before sort : ");
for(int i=0;i<N;i++){
double data=Math.random();
System.out.print(data+" ");
test[i]=data;
}
System.out.println();
StopWatch watch=new StopWatch();
sort(test);
double time=watch.elapsedTime();
System.out.println(time);
assert isSorted(test);
show(test);
}
}
算法分析:
对于长度为N的数组。选择排序大约需要N^2/2次比较,和N次交换
不难看出,i=0时,比较了N-1次,最坏情况即每一次比较都导致一次交换,共交换N-1次,i=1时,比较了N-2次,最坏情况交换N-2次,以此类推,最坏情况下,需要比较,交换(N-1)+(N-2)+(N-3)+…+2+1=N*(N-1)/2 ~ N^2/2
算法特性:
运行时间和输入无关
数据移动最少
插入排序
逐项从数组中取出项,将该项与前面各项逐个进行比较,直至其大于前一项小于后一项。
package cn.ywrby.sorts;
import cn.ywrby.tools.StopWatch;
public class InsertionSort {
public static void sort(Comparable[] a) {
int N=a.length;
for(int i=0;i<N-1;i++){
for(int j=i+1;j>0&&less(a[j],a[j-1]);j--) {
exch(a,j,j-1);
}
}
}
private static boolean less(Comparable v, Comparable w) {
return v.compareTo(w) < 0;
}
private static void exch(Comparable[] a, int i, int j) {
Comparable temp = a[i];
a[i] = a[j];
a[j] = temp;
}
private static void show(Comparable[] a) {
System.out.print("After sort : ");
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
System.out.println();
}
public static boolean isSorted(Comparable[] a) {
for (int i = 0; i < a.length-1; i++) {
if (!less(a[i],a[i+1])){return false;}
}
return true;
}
public static void main(String[] args){
int N=200;
Comparable<Double>[] test=new Comparable[N];
System.out.print("before sort : ");
for(int i=0;i<N;i++){
double data=Math.random();
System.out.print(data+" ");
test[i]=data;
}
System.out.println();
StopWatch watch=new StopWatch();
sort(test);
double time=watch.elapsedTime();
show(test);
System.out.println("time="+time);
}
}
算法分析:
最坏情况下,需要N2/2次比较和交换,一般情况下需要N2/4次比较和交换,最好情况下需要N-1次比较和0次交换
最坏情况就是每次比较都要进行交换,并且每一项进行的比较都达到最大值(从当前位置到达数组首端),所以其运行过程中比较和交换次数=(1+2+3+…+(N-1)) ~ N^2/2
算法特性:
插入排序在处理部分有序的数组时是极其高效的
插入排序对于小规模数组也是高效的
希尔排序
插入排序的主要问题在于无法处理大型数组,以及面对非部分有序数组时并不高效,希尔排序有效解决了这个问题
希尔排序首先确定一个h,将以h为间隔的元素设为一组,分别对各组进行插入排序(利用了插入排序对于小数组高效的特性),然后逐渐缩小h,使数组部分有序,当h为1时,也就彻底成为了插入排序(由于此时数组已符合部分有序,所以插入排序依然高效)
package cn.ywrby.sorts;
import cn.ywrby.tools.StopWatch;
import java.util.Random;
public class ShellSort {
public static void sort(Comparable[] a) {
int N=a.length;
int h=1;
while(h<N/3){h=3*h+1;}
while(h>=1){
for(int i=h;i<N;i++){
for(int j=i;j>=h&&less(a[j],a[j-h]);j-=h){
exch(a,j,j-h);
}
}
h=h/3;
}
}
private static boolean less(Comparable v, Comparable w) {
return v.compareTo(w) < 0;
}
private static void exch(Comparable[] a, int i, int j) {
Comparable temp = a[i];
a[i] = a[j];
a[j] = temp;
}
private static void show(Comparable[] a) {
System.out.print("After sort : ");
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
System.out.println();
}
public static boolean isSorted(Comparable[] a) {
for (int i = 0; i < a.length-1; i++) {
if (!less(a[i],a[i+1])){return false;}
}
return true;
}
public static void main(String[] args){
int N=1000;
Comparable<Double>[] test=new Comparable[N];
System.out.print("before sort : ");
for(int i=0;i<N;i++){
double data=Math.random();
System.out.print(data+" ");
test[i]=data;
}
System.out.println();
StopWatch watch=new StopWatch();
sort(test);
double time=watch.elapsedTime();
assert isSorted(test);
show(test);
System.out.println("time="+time);
}
}