实训题 4:排序算法效率比较
一 项目说明
实训目的:数组、Java API 的应用
实训要求:随机生成 10000 个 10000 以内的实数,分别用选择、冒泡、快速排序等算法进行排序,计算各种排序所需时间并比较算法的效率。
二 类设计
快速排序kuaiSuSort(int a[], int low, int high)
快速排序的基本思想就是从一个数组中任意挑选一个元素(通常来说会选择最左边的元素)作为中轴元素,将剩下的元素以中轴元素作为比较的标准,将小于等于中轴元素的放到中轴元素的左边,将大于中轴元素的放到中轴元素的右边。然后以当前中轴元素的位置为界,将左半部分子数组和右半部分子数组看成两个新的数组,重复上述操作,直到子数组的元素个数小于等于1(因为一个元素的数组必定是有序的)
排序算法效率比较Compare(long a,long b,long c)
将每个排序运行的时间进行比较,输出时间最少的那个排序算法。
三 项目实现设计
主方法中用for循环随机数的生成先生成 10000 个 10000 以内的实数,然后在各个排序前后定义一个System类的currentTimeMillis()方法,用于统计当前时间,再进行排序运算:
冒泡排序
第一步,从第一个元素开始,将相邻的两个元素依次进行比较,直到最后两个元素完成比较。如果前一个元素比后一个元素大,则交换它们的位置。整个过程完成后,数组中最后一个元素自然就是最大值,这样也就完成了第一轮比较。
第二步,除了最后一个元素,将剩余的元素继续进行比较,过程与第一步相似,这样就可以将数组中的第二大的数放在倒数第二个位置。
第三步,依次类推,持续对越来越少的元素重复上面的步骤,直到没有任何一对元素需要比较为止。然后输出运行时间。
选择排序
第一步,每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置
第二步,再从剩余未排序元素中继续寻找最小(大)元素,然后放到刚才已排序序列的后面。
第三步,以此类推,直到全部待排序的数据元素排完。然后输出运行时间。
四 运行与测试
五 分析与总结
首先我第一反应就是,要比较他们之间的效率,那么就要用到数学中的控制变量法来做了,那么我就要控制他们要比较的数字相同,所以我定义了三个数组,用来保存随机生成的10000个实数,然后只要他们的算法不一样就好了。冒泡排序我以前也写过,具体分析我已经写在项目实现设计中了。其他的排序方法的分析也在上面,讲讲我遇到的困难吧,再写冒泡排序和选择排序的时候,一切的进行的十分顺利,在写快速排序的时候我还以为和二分查找算法一样呢,没想到不是,只好去查了下资料,比二分查找算法复杂多了,通过这个实训,我学到了快速算法,发现快速算法是这几个算法中效率最高的。
package experiment.four;
import java.util.Random;
public class SortCompare {
public static void main(String[] args) {
long efficiency1,efficiency2,efficiency3;
int key[] = new int[10000];
int temp;//定义一个中间变量,用来交换数字
Random random = new Random();
//产生1000个随机数
for (int i = 0; i < 10000; i++) {
key[i] = random.nextInt(10000);
}
// 创建一个临时数组,把生成的随机数组存储起来
int key2[] = key;
// 冒泡排序start
long startTime = System.currentTimeMillis();
// 外层循环定义需要比较的轮数(两数比较,要比较n-1轮)
for (int i = 0; i < key2.length - 1; i++)
// 内层循环从i开始比较
for (int j = 0; j < key2.length - i - 1; j++) {
if (key2[j + 1] < key2[j]) {
temp = key2[j];
key2[j] = key2[j + 1];
key2[j + 1] = temp;
}
}
long endTime = System.currentTimeMillis();
efficiency1=endTime - startTime;
System.out.println("冒泡排序运行时间:" + (endTime - startTime) + "ms");
// 冒泡排序end
// 选择排序start
int key3[] = key;//保证比较的数组一样,控制变量法
long startTime1 = System.currentTimeMillis();
// 总共比较n-1次
for (int i = 0; i < key3.length - 1; i++) { // 做第i趟排序
int k = i;
for (int j = k + 1; j < key3.length; j++) {// 选出最小的一个元素放在前面
if (key3[j] < key3[k]) {
k = j; // 记下目前找到的最小值所在的位置
}
// 在内层循环结束,也就是找到本轮循环的最小的数以后,再进行交换
if (i != k) { // 交换a[i]和a[k]
temp = key3[i];
key3[i] = key3[k];
key3[k] = temp;
}
}
}
long endTime1 = System.currentTimeMillis();
efficiency2=endTime1 - startTime1;
System.out.println("选择排序运行时间:" + (endTime1 - startTime1) + "ms");
// 选择排序end
// 快速排序start
int key4[] = key;
int start = 0;
int end = key4.length - 1;
long startTime2 = System.currentTimeMillis();
SortCompare.kuaiSuSort(key4, start, end);//调用排序算法
long endTime2 = System.currentTimeMillis();
efficiency3=endTime2 - startTime2;
System.out.println("快速排序运行时间:" + (endTime2 - startTime2) + "ms");
// 快速排序end
//比较各算法的效率start
SortCompare.Compare(efficiency1,efficiency2,efficiency3);
//比较各算法的效率end
}
public static void kuaiSuSort(int a[], int low, int high) {
int start = low;
int end = high;
int key = a[low];
while (end > start) {
// 从后往前比较
while (end > start && a[end] >= key)
// 如果没有比关键值小的,比较下一个,直到有比关键值小的交换位置,然后又从前往后比较
end--;
if (a[end] <= key) {
int temp = a[end];
a[end] = a[start];
a[start] = temp;
}
// 从前往后比较
while (end > start && a[start] <= key)
// 如果没有比关键值大的,比较下一个,直到有比关键值大的交换位置
start++;
if (a[start] >= key) {
int temp = a[start];
a[start] = a[end];
a[end] = temp;
}
// 此时第一次循环比较结束,关键值的位置已经确定了。左边的值都比关键值小,右边的值都比关键值大,但是两边的顺序还有可能是不一样的,进行下面的递归调用 }
}
if (start > low)
SortCompare.kuaiSuSort(a, low, start - 1);// 左边序列。第一个索引位置到关键值索引-1
if (end < high)
SortCompare.kuaiSuSort(a, end + 1, high);// 右边序列。从关键值索引+1到最后一个
}
public static void Compare(long a,long b,long c) {
if(a<b&&a<c)
System.out.println("<<-------------冒泡排序的效率最高------------->>");
if(b<a&&b<c)
System.out.println("<<-------------选择排序的效率最高------------->>");
if(c<a&&c<b)
System.out.println("<<-------------快速排序的效率最高------------->>");
}
}
来源:CSDN
作者:九层之台 始于垒土
链接:https://blog.csdn.net/dwjdj/article/details/104307218