1 万条数据量测试排序算法
在 ArrayGenerator 类中实现 generateOrderedArray() 这样的 顺序数组的方法 去将
generateRandomArray() 提供的乱序数组进行排序
但是我们提供的数据肯定是乱序的 才要进行排序
我们为了提供乱序的数据 设置方法 generateRandomArray() 也就是生成随机数组(无序数组)
generateRandomArray() ===> 生成随机数组 ====> generateOrderedArray 去排序 =====>返回结果给ArrayGenerator
package src;
import java.util.Random;
/**
* @author xxz
* @version 1.0
* @Created on: 2024-01-17 13:37
* @Description: 使用整形Integer这个数据类型进行测试
*/
public class ArrayGenerator {
private ArrayGenerator(){}
// generateOrderedArray将 generateRandomArray随机生成的数组 进行顺序排序
public static Integer[] generateOrderedArray(int n){
Integer[] arr = new Integer[n];
for (int i = 0; i < n; i++)
arr[i] = i;
return arr;
}
// 生成一个长度为 n 随机数组,每个数字的范围是 [0,bound)
// 设置随机生成数组【乱序】的 generateRandomArray方法 并也返回 Integer 类型的数组
public static Integer[] generateRandomArray(int n, int bound) {
Integer[] arr = new Integer[n]; // 设置随机生成的数组大小n
Random rnd = new Random(); // 使用Random 来生成随机的数值
for (int i = 0; i < n; i++)
arr[i] = rnd.nextInt(bound); // bound 为随机数生成的最大的那个边界在那里
// 这一步是为数组的第i个元素赋予一个随机生成的整数值。
// `rnd.nextInt(bound)` 是使用`Random`对象(在这里是`rnd`)生成一个随机的整数值。
// `bound` 参数指定了生成的随机数的上限,即生成的随机数将在0(包括)到`bound`(不包括)之间。
// 将生成的随机数赋值给数组`arr`的第i个元素,即 `arr[i] = rnd.nextInt(bound);
// 可以在数组中的每个位置都存储一个随机生成的整数,这些整数的范围在0到`bound-1`之间。
return arr;
}
}
接下来就可以使用 这个随机生成数组的方法了 我们要的数据量的大小 通过定义n 来确定
package src;
public class SelectionSort_04 {
private SelectionSort_04(){}
public static <E extends Comparable<E>> void sort (E [] arr){ //进行实现 Comparable 接口来实现泛型可以进行1比较
for (int i = 0; i < arr.length; i++) {
int minIndex = i ;
// 选择 arr[i...n]中最小的索引
for(int j = i; j<arr.length; j++){
if (arr[j].compareTo(arr[minIndex])<0)
minIndex = j;
}
swap(arr, i ,minIndex);
}
}
//修改 swap方法 为泛型方法
private static <E> void swap(E [] arr, int i ,int j){
E t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
// 测试 1万数据量
public static void main(String[] args) {
// 设定测试数据最大量为1万
int n = 10000;
// 随机生成数组的参数1是最大容量和数组大小都设定为1万 ArrayGenerator 类只是提供了随机生成数组的方法
Integer[] arr = ArrayGenerator.generateRandomArray(n,n);
// 为了记录算法对数据的排序耗时 在排序进行前和后进行记录时间戳
long startTime = System.nanoTime(); // 开始时间
// 使用上面的排序算法进行排序
SelectionSort_04.sort(arr);
long endTime = System.nanoTime(); // 结束时间
//换算时间 time 来接受 结果
double time = (endTime - startTime) / 1000000000.0;
System.out.println("测试1万条数据进行排序花费时间"+time+ " 秒");
}
}
这里没有进行 算法执行完 对生成的排序数组的验证 只是求得算法执行的时间性能 不够严谨 !!!!!
继续优化:
这样执行完我们只得到了算法执行完的时间 但是我们到底排序是否正确呢?
我们就会思考 :
那我们执行完 我们需要对我们执行的结果进行验证,来检验结果是否正确 不然只有性能时间 不能证明算法执行的是我们想要的结果 应该怎么做呢?
我们在数据量小的时候 可以进行控制台打印 用肉眼直观的看是正确 那现在 1万条数据我们总不能一个一个打印去看排序结果是否排序正确吧 那怎么处理呢?
思路:
我们只需要验证一下 这个生成的数组是不是有序的 无论是升序还是降序 只要有序 那我们排序算法就是正确的 这样验证性能时间才是正确的
也就是说 我们 将执行完排序的 数组 从头到尾的扫描比对一下 每两个相邻的数据元素 是否都满足 前一个元素是否都 小于 后一个元素 要是满足 我们排序算法就是
正确的 。
我们来做这个步骤:
将验证封装进方法 当使用的时候去调用 判断数组是否有序的方法
起名:SortingHelper
辅助验证排序算法结果是否正确
思路:将执行完排序得到的数组 从头到尾的扫描比对一下 每两个相邻的数据元素 是否都满足 前一个元素是否都 小于 后
一个元素
package src;
/**
* @author xxz
* @version 1.0
* @Created on: 2024-01-17 14:26
* @Description: 辅助验证排序算法是否正确
*/
public class {
private SortingHelper() {}
// 返回值为布尔值 true false 同时这个isSorted()方法 是泛型方法 这个数组也是泛型数组
// 并且为了进行有序比较 那么这个必须是可比较的 而实现可比较 就需要有泛型约束 就得实现 Comparable 接口 重复在提
public static <E extends Comparable<E>> boolean isSorted(E[] arr) {
for (int i = 1; i < arr.length; i++)
// 为什么循环从 1 开始 是因为我每次要在循环中比较的是 arr[i-1]于arr[i] 的大小关系 也就是1 和2 2和3 依次推后的关系
// 而使用了 Comparable接口就一定会使用到 compareTo这个方法 来进行比较
if (arr[i - 1].compareTo(arr[i]) > 0) // 此处结果要是大于0 说明使用排序算法进行排序后的数组就不是有序的 也就是说结果不对
return false;
return true; // 要是没有提示 false错误 那就证明我们排序后的数组是对的是有序的
}
}
辅助判断方法封装完成 ,现在去测试调用 将方法在报告测试算法时间性能之前 我们就进行结果的验证
SelectionSort_05 .java
package src;
/**
* @author xxz
* @version 1.0
* @Created on: 2024-01-17 14:50
* @Description: 优化的排序算法 既有排序算法也有对排序算法的结果验证 然后有算法时间性能的展示
*/
public class SelectionSort_05 {
private SelectionSort_05(){}
public static <E extends Comparable<E>> void sort (E [] arr){ //进行实现 Comparable 接口来实现泛型可以进行1比较
// arr[0.....i) 是有序的; arr[i......n)是无序的
for (int i = 0; i < arr.length; i++) {
int minIndex = i ;
// 选择 arr[i...n]中最小的索引
for(int j = i; j<arr.length; j++){
if (arr[j].compareTo(arr[minIndex])<0)
minIndex = j;
}
swap(arr, i ,minIndex);
}
}
//修改 swap方法 为泛型方法
private static <E> void swap(E [] arr, int i ,int j){
E t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
// 测试 1万数据量
public static void main(String[] args) {
// 设定测试数据最大量为1万
int n = 10000;
// 随机生成数组的参数1是最大容量和数组大小都设定为 1万 ArrayGenerator 类只是提供了随机生成数组的方法
Integer[] arr = ArrayGenerator.generateRandomArray(n,n);
// 为了记录算法对数据的排序耗时 在排序进行前和后进行记录时间戳
long startTime = System.nanoTime(); // 开始时间
// 使用上面的排序算法进行排序
SelectionSort_05.sort(arr);
long endTime = System.nanoTime(); // 结束时间
//换算时间 time 来接收 结果
double time = (endTime - startTime) / 1000000000.0;
// SortingHelper 调用isSorted()来验证结果是否有序 也就是排序算法是否有效 要是有效 我们计算算法时间性能有价值 要是无效 就数组都没排序 计算性能没用
// 验证结果是否有效 要无效的话 我就抛出异常
if (!SortingHelper.isSorted(arr))
throw new RuntimeException("验证结果数组不是有序的,所以排序算法失效");
System.out.println("测试1万条数据进行排序花费时间"+time+ " 秒");
}
}
测试出异常的 情况: