选择排序:
public static void sort(Comparable[] a){
int N=a.length;
for(int i=0;i<N;i++){
//min保存最小的元素的下标
int min=i;
for(int j=i+1;j<N;j++)
//遇到更小的,更新下标
if(less(a[j],a[min])) min=j;
//交换
exch(a,i,min);
}
}
插入排序:
public static void sort(Comparable[] a){
int N=a.length;
for (int i = 1; i < N; i++) {
//相当于前i-1个牌都是有序的,再摸第i张牌,插入到前i-1张牌某个位置上
Comparable tmp=a[i];
int j;
for(j=i;j>0&&less(tmp,a[j-1]);j--){
//如果这张牌比前面的牌小,就后移,直到前面的牌比他大,或者已经到最前面了,就到了他正确的位置
a[j]=a[j-1];
}
//插入
a[j]=tmp;
}
}
希尔排序:
public static void sort(Comparable[] a){
int N=a.length;
int h=1;
//希尔增量 1/2(3的k次方-1)
while(h<N/3) h=3*h+1; //1,4,13,40,121,364
while(h>=1){
//每h个元素是有序
for(int i=h;i<N;i++){
Comparable tmp=a[i];
//将a[i]插入到a[i-h],a[i-2h].....
int j;
for(j=i;j>=h&&less(tmp,a[j-h]);j-=h){
a[j]=a[j-h];
}
a[j]=tmp;
}
h/=3;
}
}
递归归并排序:
public static void sort(Comparable[] a){
Comparable[] aux=new Comparable[a.length];
for (int i = 0; i < aux.length; i++) {
aux[i]=a[i];
}
sort(a,aux,0,a.length-1);
}
private static void sort(Comparable[] a, Comparable[] aux, int lo, int hi) {
if(lo>=hi) return;
//当数组小于15时,使用插入排序,能够减少递归次数
if(hi-lo<15) {
insertSort(a,lo,hi);
return;
}
int mid=(lo+hi)/2;
//将左半边排序
sort(aux,a,lo,mid); // sort(a,,aux,lo,mid) 需要复制数组
//将右半边排序 //sort(a,aux,mid+1,hi);
sort(aux,a,mid+1,hi);
if(less(aux[mid],aux[mid+1])) /* 如果前面一个子数组最大值比后面子数组最小值小,说明已经是有序的,不需要归并了*/
return ;
//归并结果
merge(a,aux,lo,mid,hi);
private static void merge(Comparable[] a, Comparable[] aux, int lo, int mid, int hi) {
int i=lo;
int j=mid+1;
//将子数组复制到辅助数组中
/*for(int k=lo;k<=hi;k++){
aux[k]=a[k];
}*/
for(int k=lo;k<=hi;k++){
//左边用完,取右边元素
if(i>mid) a[k]=aux[j++];
//右边用完,取左边元素
else if(j>hi) a[k]=aux[i++];
//左边小于右边,取左边
else if(less(aux[i],aux[j])) a[k]=aux[i++];
//右边小于左边取右边
else a[k]=aux[j++];
}
}
}
非递归归并排序:
public static void sort(Comparable[] a){
int N=a.length;
Comparable[] aux=new Comparable[N];
for(int sz=1;sz<N;sz+=sz){
for(int lo=0;lo<N-sz;lo+=sz+sz){
//min就是最后万一数组长度不足2sz 取数组的最后一个元素
merge(a,aux,lo,lo+sz-1,Math.min(lo+sz+sz-1,N-1));
}
}
}
private static void merge(Comparable[] a, Comparable[] aux, int lo, int mid, int hi) {
int i=lo;
int j=mid+1;
//将子数组复制到辅助数组中
for(int k=lo;k<=hi;k++){
aux[k]=a[k];
}
for(int k=lo;k<=hi;k++){
//左边用完,取右边元素
if(i>mid) a[k]=aux[j++];
//右边用完,取左边元素
else if(j>hi) a[k]=aux[i++];
//左边小于右边,取左边
else if(less(aux[i],aux[j])) a[k]=aux[i++];
//右边小于左边取右边
else a[k]=aux[j++];
}
}
快速排序:
public static void sort(Comparable[] a){
sort(a,0,a.length-1);
}
private static void sort(Comparable[] a, int lo, int hi) {
//当子数组长度小于等于15的时候,使用插入排序
if(hi-lo<=14) {
insertSort(a,lo,hi);
return;
}
int j=partition(a,lo,hi); //切分,a[lo...j-1]都小于a[j],a[j+1..hi]都大于a[j]
sort(a,lo,j-1); //递归排左边
sort(a,j+1,hi); //递归排右边
}
private static int partition(Comparable[] a, int lo, int hi) {
// a[lo...j-1]都小于a[j],a[j+1..hi]都大于a[j]
int i=lo,j=hi+1;
Comparable v=a[lo]; //切分的点
while(true){
while(less(a[++i],v)); //在左边遇到比v大的
while(less(v,a[--j])); // 在右边遇到比v小的
if(i>=j) break; //已经切分好了
exch(a,i,j); //交换两个位置不对的点
}
exch(a,lo,j); //吧切分点放到正确的位置a[j]上
return j;
}
public static void insertSort(Comparable[] a,int lo,int hi){
for(int i=lo+1;i<=hi;i++){
Comparable tmp=a[i];
int j;
for(j=i;j>lo&&less(tmp,a[j-1]);j--){
a[j]=a[j-1];
}
a[j]=tmp;
}
}
堆排序:
public static void sort(Comparable[] a){
int N=a.length-1;
//从下标1开始
for(int k=N/2;k>=1;k--){
sink(a,k,N);
}
while(N>1){
exch(a,1,N--);
sink(a,1,N);
}
}
private static void sink(Comparable[] a, int k, int N) {
int parent;
int child=0;
Comparable tmp=a[k];
for(parent=k;2*parent<=N;parent=child){
child=2*parent;
if(child<N&&less(a[child],a[child+1]))
child++;
if(less(a[child],tmp)) break;
a[parent]=a[child];
}
a[parent]=tmp;
}