版权声明:本博客为博主原创文章,未经博主允许,禁止转载,谢谢合作。 https://blog.csdn.net/weixin_43971252/article/details/88409742
对数器:很多测试算法的案例,通过使用对数器可以检验你的算法是否正确。
注意:C/C++版要注意动态随机数组的大小问题和内存管理问题,之前看了有几个人的博客,都只能打印和拷贝源数组的第一个元素.
使用对数器:
1.有一个你要测试的方法a:这里以插入排序为例
template<typename T>
void insertSort(T *arr, const int size) {
if (size <= 0)
{
cout << "排序数据有误,请重新输入" << endl;
return;
}
if (size == 1)
return;
for (int i = 1; i < size; i++) { //外层循环控制插入范围为0..i以及该趟插入的数据arr[i]
for (int j = i - 1; j >= 0 && arr[j + 1] < arr[j]; j--) { //相邻位置逐个比较
myswap(arr[j], arr[j + 1]);
}
}
}
2.实现一个绝对正确的方法b(时间复杂度可以很差):C++里stl的sort
//2.绝对正确的方法b
void rightMethod(int arr[], const int size) {
sort(arr, arr + size); //使用STL提供的排序算法
}
3.实现比对的方法
//3.实现比对的方法
bool isEqual(int *arr1, int *arr2, const int size) {
if ((arr1 == nullptr&&arr2 != nullptr) || (arr1 != nullptr&&arr2 == nullptr))
return false;
if (arr1 == nullptr&&arr2 == nullptr)
return true;
for (int i = 0; i < size; i++)
if (arr1[i] != arr2[i])
return false;
return true;
}
4.把方法a与方法b比对很多次来验证方法a是否正确
//4.把方法a和方法b比对多次来验证方法a是否正确
void testAlgorithm() {
int testTime = 500000; //测试案例的个数:比对次数
int maxSize = 10;
int minValue = -100;
int maxValue = 100;
bool succeed = true;
clock_t startTime, endTime;
int size1 = 0;
startTime = clock();
for (int i = 0; i < testTime; i++) {
//因为返回堆区的数据用指针来接收,如果要想知道随机数组的大小就必须要传递一个引用变量把大小记录下来
int *arr1 = generateRandomArray(maxSize, size1, minValue, maxValue); //自己写的算法的测试数组
//cout << "size1: " << size1 << endl;
int *arr2 = copyArray(arr1, size1) ; //排序时与自己写的算法进行比较的数组,绝对正确的算法测试数组
int *arr3 = copyArray(arr1, size1); //如果算法不正确,打印该测试案例,并修改算法
mysort::selectionSort<int>(arr1, size1);
rightMethod(arr2, size1);
if (!isEqual(arr1, arr2, size1) ){
succeed = false;
printArray(arr3, size1);
break;
}
delete arr1; //回收堆区内存
delete arr2;
delete arr3;
}
if (succeed)
cout << "Nice!" << endl; //6.当足够多的样本都对,那么可以确定方法a已经正确
else
cout << "Fucking fucked!" << endl;
endTime = clock();
cout << "time cost : " << (double)(endTime - startTime) / CLOCKS_PER_SEC << " s" << endl;
}
补充:产出随机数组和拷贝数组的方法,产出数组大小和数组的元素值都不确定的堆区数组时,要特别小心:要传递一个引用类型的参数,用来记录动态数组有多少个元素,这样在拷贝数组和打印数组时才是整个数组。
//srand()和rand()在<iostream>, time()在<ctime>
int* generateRandomArray(int maxSize, int& size, int minValue, int maxValue) {
assert(minValue < maxValue);
srand((unsigned int)time(NULL)); //提供随机种子
size = rand() % maxSize + 1; //rand()产生0到RAND_MAX伪随机整数,% 所得余数小于maxSize,再+1后小于等于maxSize
int *arr = new int[size];
for (int i = 0; i < size; i++) {
arr[i] = rand() % (maxValue - minValue) + minValue + 1; //minValue <= arr[i] <= maxValue
}
return arr;
}
//拷贝数据时,数组做为形参退化为普通指针*a,所以需要参数n来确定拷贝的元素的个数
int *copyArray(int a[], const int n) {
if (a == nullptr)
return nullptr;
//cout << "n : " << n << endl;
int *arr = new int[n];
copy(a, a + n, arr);
return arr;
}
5.如果有一个样本出错,打印出错的样本,并分析是哪个算法错误;打印时要注意,因为数组作为形参时退化为指针,要有一个参数告诉数组有多少个元素,这样才能打印整个数组。
//5.如果有一个样本出错,打印样本分析是哪个方法出错
//打印数组和拷贝数组同理
void printArray(int arr[], const int n) {
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
cout << endl;
}
6.当样本量足够多而且比对测试仍然正确,可以确定方法a已经正确。
祝贺你,你的算法是对的。
头文件:
#include<iostream>
#include<ctime>
#include<algorithm>
#include<cassert>
using namespace std;