本篇文章针对现有常用的排序算法进行比较,并计算出排序所用的时间。
待排序的个数:100000
待排序数值的范围:0~1000
1 简化版桶排序法
1 import java.util.Random; 2 3 /*对0~10000之间的100000个数从小到大排序 4 * 简化桶排序法 5 * 祁俊辉 17.5.2 6 * */ 7 public class Tong { 8 static int a[]=new int[100000];//定义存储100000个待排序数的数组 9 static int b[]= new int[100001];//定义桶,范围0~100000,所以共10001个桶 10 //定义一个简易桶排序的方法 11 static void BarrelSort(int[] Dai,int[] Tou){//传入待排序数组、桶数组 12 for(int i=0;i<Dai.length;i++){ 13 Tou[Dai[i]]++; 14 } 15 } 16 //生成随机数 17 static int RandomMM(int min,int max){ 18 Random random = new Random(); 19 int s = random.nextInt(max)%(max-min+1) + min; 20 return s; 21 } 22 //主方法 23 public static void main(String[] args) { 24 long starTime=System.currentTimeMillis();//当前时间赋给一个变量 25 for(int i=0;i<a.length;i++){ 26 a[i] = RandomMM(0,10000); 27 } 28 BarrelSort(a,b);//桶排序调用 29 //输出排序后的结果 30 //遍历桶,为0的不打印(说明没出现过),1以上的循环打印(防止同一个数多次出现) 31 for(int i=0;i<b.length;i++){ 32 for(int j=1;j<=b[i];j++){ 33 System.out.println(i); 34 } 35 } 36 long endTime=System.currentTimeMillis();//当前时间赋给一个变量 37 long time=endTime-starTime;//计算所用时间 38 System.out.println("对100000个“0~10000”范围的整数排序(冒泡排序法):"+time+"ms");//输出时间 39 } 40 }
2 冒泡排序法
1 import java.util.Random; 2 3 /*对0~10000之间的100000个数从小到大排序 4 * 冒泡法 5 * 祁俊辉 17.5.2 6 * */ 7 public class Mao { 8 static int a[]=new int[100000];//定义存储100000个待排序数的数组 9 //定义一个冒泡排序的方法 10 static void BubbleSort(int[] Dai){ 11 for(int i=1;i<Dai.length;i++){//n个数排序,只需进行n-1趟操作(一次操作只将1个数归位) 12 for(int j=0;j<Dai.length-i;j++){//第一趟比较n-1次,第二趟比较n-2次。。。 13 if(Dai[j]>Dai[j+1]){//不满足条件,交换 14 int temp=a[j]; 15 Dai[j]=Dai[j+1]; 16 Dai[j+1]=temp; 17 } 18 } 19 } 20 } 21 //生成随机数 22 static int RandomMM(int min,int max){ 23 Random random = new Random(); 24 int s = random.nextInt(max)%(max-min+1) + min; 25 return s; 26 } 27 //主方法 28 public static void main(String[] args) { 29 long starTime=System.currentTimeMillis();//当前时间赋给一个变量 30 for(int i=0;i<a.length;i++){ 31 a[i] = RandomMM(0,10000); 32 } 33 BubbleSort(a);//冒泡排序调用 34 //输出排序后的结果 35 for(int i=0;i<a.length;i++){ 36 System.out.println(a[i]); 37 } 38 long endTime=System.currentTimeMillis();//当前时间赋给一个变量 39 long time=endTime-starTime;//计算所用时间 40 System.out.println("对100000个“0~10000”范围的整数排序(冒泡排序法):"+time+"ms");//输出时间 41 } 42 }
3 快速排序法
1 import java.util.Random; 2 3 /*对0~10000之间的100000个数从小到大排序 4 * 快速排序法 5 * 祁俊辉 17.5.2 6 * */ 7 public class Kuai { 8 static int a[]=new int[100000];//定义存储100000个待排序数的数组 9 //定义一个快速排序的方法 10 static void QuickSort(int[] Dai,int left,int right){//传入待排序数组、左右下标 11 int i,j,t,temp; 12 if(left>right)//如果越界,则表示出错,直接退出 13 return; 14 temp=Dai[left];//存储基准数 15 i=left; 16 j=right; 17 while(i!=j){ 18 while(Dai[j]>=temp && i<j)//注意顺序,先从右往左,要不然会落下一个数 19 j--; 20 while(Dai[i]<=temp && i<j)//再从左往右 21 i++; 22 if(i<j){//没有相遇,则交换 23 t=Dai[i]; 24 Dai[i]=Dai[j]; 25 Dai[j]=t; 26 } 27 } 28 //运行到这里,说明左右相遇了,将基准数归位 29 Dai[left]=Dai[i]; 30 Dai[i]=temp; 31 //左右递归运算 32 QuickSort(Dai,left,i-1);//继续处理左边的,递归 33 QuickSort(Dai,i+1,right);//继续处理右边的,递归 34 } 35 //生成随机数 36 static int RandomMM(int min,int max){ 37 Random random = new Random(); 38 int s = random.nextInt(max)%(max-min+1) + min; 39 return s; 40 } 41 //主方法 42 public static void main(String[] args) { 43 long starTime=System.currentTimeMillis();//当前时间赋给一个变量 44 for(int i=0;i<a.length;i++){ 45 a[i] = RandomMM(0,10000); 46 } 47 QuickSort(a,0,a.length-1);//快速排序调用 48 //输出排序后的结果 49 for(int i=0;i<a.length;i++){ 50 System.out.println(a[i]); 51 } 52 long endTime=System.currentTimeMillis();//当前时间赋给一个变量 53 long time=endTime-starTime;//计算所用时间 54 System.out.println("对100000个“0~10000”范围的整数排序(快速排序法):"+time+"ms");//输出时间 55 } 56 }
4 堆排序法(完全二叉树)
1 import java.util.Random; 2 3 /*对0~10000之间的100000个数从小到大排序 4 * 堆排序法(堆:完全二叉树) 5 * 祁俊辉 17.5.2 6 * */ 7 public class Dui { 8 static int a[]=new int[100001];//定义存储100000个待排序数的数组,下标从1~100000 9 static int n=a.length-1;//待排序个数,也就是堆的大小 10 //交换函数,用来交换堆中两个元素的值 11 static void swap(int[]Dai,int x,int y){ 12 int temp; 13 temp=Dai[x]; 14 Dai[x]=Dai[y]; 15 Dai[y]=temp; 16 } 17 //向下调整函数 18 static void siftdown(int[] Dai,int i){//传入待排数组和需要向下调整的下标 19 int t,flag=0;//flag用来标记是否需要继续向下调整 20 //当i结点有儿子(左)并且有需要继续调整的时候循环执行 21 while(i*2<=n && flag==0){ 22 //首先判断左边,并用t记录值较小的结点编号 23 if(Dai[i] > Dai[i*2]) 24 t=i*2; 25 else 26 t=i; 27 //如果它有左边,在对右边进行讨论 28 if(i*2+1 <= n){ 29 if(Dai[t] > Dai[i*2+1]) 30 t=i*2+1; 31 } 32 //如果发现最小的结点编号不是自己,说明子结点中有比父结点更小的 33 if(t!=i){ 34 swap(Dai,t,i);//交换它们 35 i=t;//更新i 36 }else{ 37 flag=1;//否则说明当前父结点已经比它的子节点小,不需要进行调整 38 } 39 } 40 } 41 //建立堆的函数 42 static void creat(int[] Dai){ 43 //从最后一个非页结点到第一个结点依次进行向下调整 44 for(int i=n/2;i>=1;i--) 45 siftdown(Dai,i); 46 } 47 //删除最大的元素 48 static int deletemax(int[] Dai){ 49 int t=Dai[1];//用一个临时变量记录堆的顶点的值 50 Dai[1]=Dai[n];//将堆的最后一个点赋值到堆顶 51 n--;//堆的元素减1 52 siftdown(Dai,1);//向下调整 53 return t;//返回之前记录的堆的顶点的最大值 54 } 55 //生成随机数 56 static int RandomMM(int min,int max){ 57 Random random = new Random(); 58 int s = random.nextInt(max)%(max-min+1) + min; 59 return s; 60 } 61 //主函数 62 public static void main(String[] args) { 63 long starTime=System.currentTimeMillis();//当前时间赋给一个变量 64 for(int i=0;i<a.length;i++){ 65 a[i] = RandomMM(0,10000); 66 } 67 creat(a);//建堆 68 //删除顶部元素,连续删除n次,其实就是从小到大把数输出来 69 for(int i=1;i<=n;i++) 70 System.out.println(deletemax(a)); 71 long endTime=System.currentTimeMillis();//当前时间赋给一个变量 72 long time=endTime-starTime;//计算所用时间 73 System.out.println("对100000个“0~10000”范围的整数排序(快速排序法):"+time+"ms");//输出时间 74 } 75 }
5 总结
以上只对四种排序方法进行比较,后期将持续更新。
简化版桶排序主要针对数值范围小、待排序个数多的数进行排序,因为数值范围直接影响它要设置多少个桶。
冒泡排序只是一种思想,在实际应用中不会应用,因为不管何种情况,效率太慢!
快速排序是一个值得推荐的排序方法。
堆排序法是从最小堆(完全二叉树)中扩展出来的,排序过程也是非常快速(也可以用最大堆进行排序,可以避免建立堆的过程,可能会更优化)。