最近在看左神的算法初级班视频,接触到一个新名词----对数器,想简单记录一下。
对数器的概念和使用
对数器就是一个绝对正确的方法(没有时间和空间复杂度的限制的)和能产生大量随机样例的随机器的组合。
对数器的作用:验证算法是否正确。
使用场景:在笔试中,当我们写出的算法逻辑上大致正确,但还不确定它是否满足所有的要求,此时就需要对数器的帮助了。它能通过大量的数据集验证算法的正确性。而我们在时间紧迫的情况下,往往会考虑不周,无法想到涵盖某些特殊情况的测试用例。所以就需要生成大量随机发的测试用例,希望它能包括各种情况,把算法可能遇到的各个方面都要考虑到。
此法宝为笔试神器,提前准备好某些满足要求的对数器,会大大提高答题效率。
PPT内容
0,有一个你想要测的方法a,
1,实现一个绝对正确但是复杂度不好的方法b,
2,实现一个随机样本产生器
3,实现比对的方法
4,把方法a和方法b比对很多次来验证方法a是否正确。
5,如果有一个样本使得比对出错,打印样本分析是哪个方法出错
6,当样本数量很多时比对测试依然正确,可以确定方法a已经正确。
注意:
- 随机产生的样本应该是小数据集,但是要进行多次(10w+)的对比。小数据集是因为方便对比分析,多次比对是要覆盖所有的随机情况。
- 算法b也无法保证完全的正确,在不断出错调试的过程中,也可以不断完善b,最终达到a和b都正确的完美结果。
对数器代码示例
1、实现要测试的方法a,此处测试冒泡排序
template<class Type>
void Swap(Type &a, Type &b) {
Type tmp = a;
a = b;
b = tmp;
}
void BubbleSort(vector<int> arr) {
if (arr.empty() || arr.size() < 2)
return;
for (int i = 0; i < arr.size() - 1; ++i) {
for (int j = arr.size() - 1; j > i; --j) {
if (arr[j] < arr[j - 1])
Swap(arr[j], arr[j - 1]);
}
}
}
void testAlgorithm(vector<int> arr) {
BubbleSort(arr);
}
2、实现一个完全正确的算法b,用的是系统的排序函数sort
void comparator(vector<int> arr) {
sort(arr.begin(), arr.end());
}
3、实现一个随机样本产生器
vector<int> generateRandomArr(int maxSize, int maxValue) {
int size = rand() % (maxSize + 1); // 生成长度随机[0, size]的数组
vector<int> arr(size);//初始化定义数组
for (int i = 0; i < size; i++) {
arr[i] = rand() % (2 * maxValue + 1) - maxValue; //生成[-value, value]的随机数
}
return arr;
}
4、实现比对的方法,此处是将两个算法排序后的数组进行对比,是否一致
bool isEqual(vector<int> arr1, vector<int> arr2) {
if ((!arr1.empty() && arr2.empty()) || (arr1.empty() && !arr2.empty())) {
return false;
}
if (arr1.empty() && arr2.empty()) {
return true;
}
if (arr1.size() != arr2.size()) {
return false;
}
for (int i = 0; i < arr1.size(); ++i) {
if (arr1[i] != arr2[i]) {
return false;
}
}
return true;
}
5、其他辅助函数
//拷贝一个完全一样的数组
vector<int> copyArr(vector<int> arr) {
if (arr.empty()) {
return arr;
}
vector<int> copy(arr.size());
for (int i = 0; i < arr.size(); i++) {
copy[i] = arr[i];
}
return copy;
}
//打印数组
void printArr(vector<int> arr) {
if (arr.empty()) {
return;
}
for (int i = 0; i < arr.size(); i++) {
cout << arr[i] << ',';
}
cout << endl;
}
6、运行测试程序,验证方法a是否正确
void RunLogarithmDetector() {
int testTime = 1000;
int maxSize = 10;
int maxValue = 50;
bool successed = true;
for (int i = 0; i < testTime; i++) {
cout << "No." << testTime << endl;
vector <int> arr1 = generateRandomArr(maxSize, maxValue);
cout << "original array is: ";
printArr(arr1);
vector<int> arr2 = copyArr(arr1);
testAlgorithm(arr1);
comparator(arr2);
cout << "sorted array is: ";
printArr(arr1);
if (!isEqual(arr1, arr2)) {
successed = false;
break;
}
}
string res = successed ? "Nice!" : "Error!";
cout << res << endl;
}