1.Java实现各种排序

来源:互联网 发布:js 全局变量 丢失属性 编辑:程序博客网 时间:2024/06/04 19:47

下文是根据《算法-第四版》编写的排序代码,与大话数据结构中可能有出入,但思想是一样的,灵活多变的算法呀!


package com.yuan;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.util.Arrays;import java.util.Collections;import java.util.List;import java.util.Random;import java.util.Scanner;public class Selection {       //-------------------------------------几种排序方法-------------------------------------//       private static Comparable[] aux;//归并排序需要的辅助数组              //选择排序      1.基本思想:从数组的第一个元素开始,对数组中的每一个元素都执行——与后面的元素一一比较,记录元素值最小的索引下标,一开始将当前元素的下表设为min,与后面所有元素比较完毕以后,可以得到最小值的小标,然后交换最小值和当前元素。      2.  时间复杂度       public static void sort_Selection(Comparable[] a){              int N=a.length;              for(int i=0;i<N;i++){                     int min=i;                     for(int j=i+1;j<N;j++){                           if(less(a[j],a[min]))                                  min=j;                     }                     exch(a,i,min);              }       }              //插入排序       1.基本思想:对数组中从第二项往后的每一项元素,执行——比较它与前面的元素的大小,前面的元素中比当前元素大的就往后移动一位,一直到比它小,此时j指向比当前元素小的那个位置,所以要把当前元素插入在a[j+1]处。       public static void sort_Insertion(Comparable[] a){              int N=a.length;              int i,j;              for(i=1;i<N;i++){                     Comparable temp=a[i];                     for(j=i-1;j>=0 && less(temp,a[j]); j--){                           a[j+1]=a[j];                     }                     a[j+1]=temp;              }       }       //希尔排序       1.基本思想:插入排序的升级版,插入排序是当前元素和它前面的元素一个一个的比较,希尔排序是与每间隔h的元素才比较                   大致有序---->全部有序,元素移动次数更少,效率更高                   h的变化:从一个比较大的值,每排序一次,就变为h/3,缩小间隔。最后一次排序的间隔应该是1.                     public static void sort_Shell(Comparable[] a){              int N=a.length;              int h=1;              while(h<N/3)                     h = 3*h+1;              while(h>=1)              {                     //将数组变为h有序                     int i,j;                     for(i=h; i<N; i++){                           Comparable temp=a[i];                           for(j=i-h; j>=h && less(temp,a[j]);j-=h){                                  a[j+h]=a[j];                           }                           a[j+h]=temp;                     }                     h=h/3;              }       }              //自顶向下的归并排序      1.基本思想:将整个数组从中间分成两块,然后再分别对分裂后的两块也执行从中间分裂的操作,一直循环直到一个块只包含一个元素,就返回上一层,执行右半边的sort()函数,发现也不能再分裂了,又返回,接着执行merge函数将数组的前两个元素合并(合并的过程就是排序的过程,这里需要申请另外一个相等的数组内存空间,用于存放原数组的备份,排序后依次存放在原数组中),第一次合并后sort执行完毕返回到上一层,接着执行右半边的sort(),对第三、四个元素排序合并,返回执行1234元素的合并操作...以此递归,直到返回到第一层,数组排序完毕。      2.merge函数:4个参数(数组a,要合并的数组的头、界限、尾),从两个数组的第一个元素开始比较,交叉尽心个,小的就放在数组a[]中,且对应的指针向后移动继续比较。如果其中一个数组先比较完,则把另一个数组剩余的元素依次添加到数组a[]的后面。       public static void sort_Merg(Comparable[] a){              aux= new Comparable[a.length];              sort(a,0,a.length-1);       }             public static void merge(Comparable[] a, int lo, int mid, int hi){              //原地归并的抽象方法              int i=lo, 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[j],aux[i]))                           a[k]=aux[j++];                     else                           a[k]=aux[i++];              }       }       private static void sort(Comparable[] a, int lo, int hi){              //归并排序的sort方法              if(hi<=lo) return;              int mid=lo+(hi-lo)/2;              sort(a,lo,mid);              sort(a,mid+1,hi);              merge(a,lo,mid,hi);       }              //自底向上的归并排序       1.基本思想:与自顶向下相反的是,从单独的一个元素开始执行合并操作,而不是首先对整个数组进行分裂。                 合并尺寸:一开始是将两个元素合并在一起,所以合并尺寸是1,合并后数组大小变为2,所以下一次的合并尺寸是2倍的。                 从第一个元素开始,两两合并for(int lo=0; lo<N-sz; lo=lo+2*sz)  merge(a,lo,lo+sz-1,Math.min(lo+2*sz-1,N-1));       public static void sort_MergeBU(Comparable[] a){              int N=a.length;              aux= new Comparable[N];              for(int sz=1; sz<N; sz=sz*2){                     for(int lo=0; lo<N-sz; lo=lo+2*sz){                           merge(a,lo,lo+sz-1,Math.min(lo+2*sz-1,N-1));                     }              }       }              //快速排序       1.基本思想:首先从数组中随机挑选一个元素值作为衡量标准,从数组的两端开始,使用两个指针(i和j),一个从头部开始,一个从尾部开始。                 循环直到从头部的指针指向的元素比当前元素大,从尾部的指针指向的元素比当前元素小,那么交换这两个元素。一直到i>=j时说明整个数组全都比较完毕。                 最后需要将当前元素放到合适的位置上。       public static void sort_Quick(Comparable[] a){              //List<Comparable> list = Arrays.asList(a);              //Collections.shuffle(list);              //a=(Comparable[]) list.toArray();              String s = sortQ(a,0,a.length-1);              System.out.printf(s+"\n");       }       private static String sortQ(Comparable[] a, int lo, int hi){              int M=50;              if(hi<=lo+M){                     sort_Insertion(a);                     return "使用的是插入排序!";              }              int j=partition(a,lo,hi);              sortQ(a,lo,j-1);              sortQ(a,j+1,hi);              return "使用的是快速排序!";       }       private static int partition(Comparable[] a, int lo, int hi) {              // TODO Auto-generated method stub              int i=lo,j=hi+1;              Comparable v=a[lo];              while(true){                     while(less(a[++i],v))                           if(i==hi)                                  break;                     while(less(v,a[--j]))                           if(j==lo)                                  break;                     if(i>=j) break;                     exch(a,i,j);              }              exch(a,lo,j);              return j;       }       //--------------------------------------------通用方法--------------------------------------//              //比较两元素大小       private static boolean less(Comparable v, Comparable w){              return v.compareTo(w)<0;       }              //交换两个元素       private static void exch(Comparable[] a, int i, int j){              Comparable t=a[i];              a[i]=a[j];              a[j]=t;       }              //显示数组内容       private static void show(Comparable[] a){              for(int i=0;i<a.length;i++){                     System.out.println(a[i]+" ");              }              System.out.println("\n");       }              //判断是否已经排序       public static boolean isSorted(Comparable[] a){              for(int i=1;i<a.length;i++)                     if(less(a[i],a[i-1]))                           return false;              return true;       }              //主函数       public static void main(String[] args) {              // TODO Auto-generated method stub              Comparable[] a;              System.out.printf("请输入数组长度N:\n");              Scanner sc = new Scanner(System.in);              int n = sc.nextInt();                            a=new String[n];              System.out.printf("请输入一个长度为%d的字符串数组,BufferedReader以换行区为标志区分不同的元素:\n",n);              for(int i=0;i<n;i++){                     //System.out.println("请输入:");                     InputStream input = System.in;                     BufferedReader buf = new BufferedReader(new InputStreamReader(input));                     String str = null;                     try {                           str = buf.readLine();                     } catch (IOException e) {                           // TODO Auto-generated catch block                           e.printStackTrace();                     }                     a[i] = str;              }              //String[] a=new String[]{"a","c","d","g","b"};              //Integer[] a=new Integer[]{5,10,3,6,1,20,11,35,26};              //sort_Selection(a);              //sort_MergeBU(a);              //sort_Insertion(a);              sort_Quick(a);              isSorted(a);              show(a);       }}//比较两种排序算法的时间复杂度package com.compare;import java.util.Random;import com.yuan.Selection;public class SortCompare {              public static long time(String alg, Long[] a){                            long t1=System.currentTimeMillis();                            if(alg.equals("sort_Insertion")) Selection.sort_Insertion(a);              if(alg.equals("sort_Selection")) Selection.sort_Selection(a);              if(alg.equals("sort_Shell")) Selection.sort_Shell(a);              if(alg.equals("sort_Merg")) Selection.sort_Merg(a);              if(alg.equals("sort_MergeBU")) Selection.sort_MergeBU(a);                            long t2=System.currentTimeMillis();              return t2-t1;       }              public static long timeRandomInput(String alg, int N, int T){              Random ra = new Random();              //使用算法alg将T个长度为N的数组排序              long total= 0 ;              Long[] a = new Long[N];              for(int t=0;t<T;t++){                     for(int i=0;i<N;i++)                           a[i]=ra.nextLong();                     total+=time(alg, a);              }              return total;       }              public static void main(String[] args) {              // TODO Auto-generated method stub              String alg1=args[0];              String alg2=args[1];              int N=Integer.parseInt(args[2]);              int T=Integer.parseInt(args[3]);              long t1=timeRandomInput(alg1,N,T);              long t2=timeRandomInput(alg2,N,T);              System.out.printf("For %d random Longs\n %s is ", N, alg1);              System.out.printf("%.1f times faster than %s\n ", (float)t2/t1, alg2);       }}