排序算法思想
选择排序:
从数据中选择最小的一个并排在第一个位置,接下来从余下的数据中选择最小的排在第二个位置,依次类推。。
算法需要N2/2次比较和N次交换
特点:
1)程序运行时间与输入无关:每一次排序都不能为下一次排序提供有用的信息。有序的数组和无序的数组排序所用的时间一样长。
2)数据移动是最少的:两两交换只需交换N次,是所有算法中交换次数最少的
package sort; public class ChooseSort { public static int[] sort(int[] a){ for(int i=0;i<a.length;i++) { int min=a[i]; int minIndex=i; for(int j=i+1;j<a.length;j++) { if(a[j]<min) { min=a[j]; minIndex=j; } } int temp=a[i]; a[i]=min; a[minIndex]=temp; } return a; } public static void main(String args[]){ int a[]={5,3,2,1,4}; int []b=sort(a); for(int i=0;i<b.length;i++) System.out.println(b[i]); } }
插入排序:
认为左边部分为有序的,每一次都将右边第一个元素放在左边那部分的适当位置,使得左边部分始终有序。而右边第一个元素也就是要插入的元素的位置腾出来之后,左边的所有比要插入元素大的数据会一次向又移。
平均需要进行N2/4次比较和N2/4次交换,最差的情况需要进行N2/2次比较和N2/2次交换
特点:
当数组本身就是一个有序数组时则不需要移动。
插入排序对于部分有序数组很有效,部分有序数组包括这种情况:数组中每个元素距离他的最终位置都不远
1 package sort; 2 3 public class InsertSort { 4 5 public static int[] sort(int []a){ 6 for(int i=1;i<a.length;i++) 7 { 8 int current=a[i]; 9 for(int j=i;j>0;j--) 10 { 11 if(a[j]<a[j-1]) 12 { 13 int temp=a[j]; 14 a[j]=a[j-1]; 15 a[j-1]=temp; 16 } 17 } 18 } 19 return a; 20 } 21 22 23 public static void main(String args[]){ 24 int a[]={3,2,1,4,9,5}; 25 a=sort(a); 26 for(int i=0;i<a.length;i++) 27 System.out.println(a[i]); 28 } 29 }
希尔排序:
希尔排序是改进后的插入排序,首先定义一个间隔d,将数组数据进行分组,用插入排序法保证每个分组内是有序的,之后缩减间隔d的值,重新分组排序,直到间隔为1时,即可保证整个数组是有序的。希尔排序充分利用了插入排序的特性,使得部分有序数组的排序性能大幅度提高。
特性:希尔排序适用于大数组,效果明显。但对于间隔d的选择却是一个问题
1 package sort; 2 3 public class ShellSort { 4 5 public static int[] sort(int []a){ 6 int d=a.length/3; 7 while(d>0){ 8 for(int i=d;i<a.length;i++) 9 { 10 for(int j=i;j>0;j=j-d) 11 { 12 if(a[j]<a[j-d]) 13 { 14 int temp=a[j]; 15 a[j]=a[j-d]; 16 a[j-d]=temp; 17 18 } 19 } 20 } 21 d--; 22 } 23 return a; 24 } 25 public static void main(String args[]){ 26 int a[]={5,3,1,4,2}; 27 a=sort(a); 28 for(int i=0;i<a.length;i++) 29 System.out.println(a[i]); 30 } 31 }
归并排序:
归并排序分为自顶向下和自底向上两种方法,自顶向下采用的是递归的方法,自底向上则是这样的:首先一个一个元素归并,之后两两归并,接着四四归并。但是归并时第二组的元素个数可能会和第一组不同。
自底向上方法:
1 package sort; 2 3 public class BottomToTopMergeSort { 4 5 /** 6 * @param args 7 */ 8 public static void main(String[] args) { 9 // TODO Auto-generated method stub 10 int a[]={5,3,2,1,4}; 11 sort(a); 12 for(int i=0;i<a.length;i++) 13 System.out.println(a[i]); 14 } 15 16 public static void merge(int[]a,int lo,int mid,int hi){ 17 int []aux=new int[a.length]; 18 for(int i=lo;i<=hi;i++) 19 aux[i]=a[i]; 20 int i=lo; 21 int j=mid+1; 22 for(int k=lo;k<=hi;k++) 23 { 24 if(i>mid) a[k]=aux[j++]; 25 else if(j>hi) a[k]=aux[i++]; 26 else if(aux[i]>aux[j]) a[k]=aux[j++]; 27 else a[k]=aux[i++]; 28 } 29 } 30 public static void sort(int []a){ 31 int len=a.length; 32 for(int size=1;size<len;size=size+size) 33 { 34 for(int lo=0;lo<len-size;lo+=size+size){ 35 merge(a,lo,lo+size-1,Math.min(lo+size+size-1, len-1)); 36 } 37 } 38 } 39 40 }
在该方法中,有两个for循环,第一个for循环用来确定归并元素的个数,第一轮是一个一个归并,第二轮是两两归并,第三轮是四四归并。第二个for循环用来进行分组归并,
for(int lo=0;lo<len-size;lo+=size+size)
从标号为0的元素开始,到长度减去归并组中元素个数,每次跨越两个组。
merge(a,lo,lo+size-1,Math.min(lo+size+size-1, len-1));
还有一点需要注意的是,因为最后无法确定还余多少个元素,因此应取长度或者正规个数最小的那个
自顶向下递归排序:
1 package sort; 2 3 public class BottomToTopMergeSort { 4 5 /** 6 * @param args 7 */ 8 public static void main(String[] args) { 9 // TODO Auto-generated method stub 10 int a[]={5,3,2,1,4}; 11 sort(a); 12 for(int i=0;i<a.length;i++) 13 System.out.println(a[i]); 14 } 15 16 public static void merge(int[]a,int lo,int mid,int hi){ 17 int []aux=new int[a.length]; 18 for(int i=lo;i<=hi;i++) 19 aux[i]=a[i]; 20 int i=lo; 21 int j=mid+1; 22 for(int k=lo;k<=hi;k++) 23 { 24 if(i>mid) a[k]=aux[j++]; 25 else if(j>hi) a[k]=aux[i++]; 26 else if(aux[i]>aux[j]) a[k]=aux[j++]; 27 else a[k]=aux[i++]; 28 } 29 } 30 public static void sort(int []a){ 31 int len=a.length; 32 for(int size=1;size<len;size=size+size) 33 { 34 for(int lo=0;lo<len-size;lo+=size+size){ 35 merge(a,lo,lo+size-1,Math.min(lo+size+size-1, len-1)); 36 } 37 } 38 } 39 40 }
浙公网安备 33010602011771号