左神算法与数据结构全阶课上笔记(3)——排序算法的对数器应用验证(C++实现)

算法与数据结构新手班(class02)——排序算法的对数器应用验证(C++实现)

B站视频地址:https://bilibili.com/video/BV1g3411i7of?p=8&spm_id_from=pageDriver
排序算法的对数器应用测试github地址: https://github.com/algorithmzuo/algorithm-primary/tree/main/src/class01

1. 对数器

尾田理解的对数器概念:自己开发算法的复杂度往往是高的,通过一种具有大量样本分析的测试程序与另一种绝对正确且复杂度较低的官方算法进行比较,从而得出自研算法是否正确,这种测试程序就叫对数器。
左神阐述的对数器概念:
1. 有一个你想要测的方法a;
2. 实现一个绝对正确但是复杂度不好的方法b;
3. 实现一个随机样本产生器;
4. 实现对比算法a和b的方法;
5. 把方法a和方法b比对多次来验证方法a是否正确;
6. 如果有一个样本使得比对出错,打印样本分析是哪个方法出错;
7. 当样本数量很多时比对测试依然正确,可以确定方法a已经正确。

————————————————
对数器的核心——随机数的原理及应用扩展已在上个博客解释:左神算法与数据结构全阶课上笔记(2)——随机数的原理与扩展应用(C++实现)

2. 随机数组的产生与测试

对数器用于判断某个算法是否准确的核心功能是随机产生一个长度随机、数据随机的样本随机数组,这个功能实现依赖于随机函数,最后通过大量测试检验算法正确性。

2.1 随机数组的产生

功能程序:

// 动态创建随机数组,数组长度和数值大小皆随机
int* lenRandomValueRandom(int maxLen, int maxValue, int& len)
{
    len = (int)(getRandom() * maxLen);
    int* ans = new int[len];  
    for(int i = 0; i < len; i++)
    {
        ans[i] = (int)(getRandom() * maxValue);
    }

    return ans;
}

程序测试结果

361 16 354 185 227 429 354 488 95 792
726 229 810 953 155 707 787 851 929 218 416 553 993 291
586 746 309 438 718 285 648 889
127 350 61 764 677 718 615 409 425 542 459
113 813 910 539 338 651 360
890 505 381 595 302 894 591 753 375 691 154 289
460 907 773 48

2.2 随机数组的应用测试——检验排序算法是否有序

功能程序:

int main(int args, char** argv)
{
    int maxLen = 20;
    int maxValue = 1000;
    int testTime = 10000;
    int arr1Len = 0;
    for(int i = 0; i < testTime; i++)
    {
        int * arr1 = lenRandomValueRandom(maxLen, maxValue, arr1Len); // 产生样本随机数组
        int * copyArr = copyArray(arr1, arr1Len); // 随机数组备份
        selectSort(arr1, arr1Len); // 调用开发的排序算法
        if(!isSorted(arr1, arr1Len)) // 检验排序算法是否有序,只是检验其是否是升序
        {
            cout << "选择排序错了" << endl;
            cout << "排序算法排序结果: " << endl;
            printArray(arr1, arr1Len);
            cout << "备份的样本数组: " << endl;
            printArray(copyArr, arr1Len);
            delete arr1; // 创建的数组都在堆区,需要释放
            delete copyArr;
            break;
        }
        arr1Len = 0;
        delete arr1;
        delete copyArr;
    }
    cout << "选择排序正确,样本测试通过! Nice!" << endl;
    return 0;
}

程序测试结果
通过结果

选择排序正确,样本测试通过! Nice!

失败结果
将排序算法从升序改为降序,样本测试不通过

选择排序错了
排序算法排序结果:
995 975 905 897 795 786 783 696 538 486 457 196 146 114 114 80 58
备份的样本数组:
114 995 897 786 146 975 905 80 486 696 58 196 795 538 783 457 114

3. 排序算法对数器的应用测试

前面的功能测试只是用来测试某算法是否有序,而真正的对数器应用应该是你的算法与其他官方算法的对比测试,大量多次的排序结果逐一对比才能真正检验算法是否准确无误。下面将以插入排序为例,以一维数组和STL库vector分别实现对数器的应用测试。相关排序算法原理可见:左神算法与数据结构全阶课上笔记(1)——排序算法(C++实现)

3.1 一维数组实现

  1. 主程序
int main(int args, char** argv)
{
    int maxLen = 20;
    int maxValue = 1000;
    int testTime = 10000;
    int arr1Len = 0;
    bool succeed = true;
    cout << "-----调用insertSort实现插入排序-----" << endl;
    for(int i = 0; i < testTime; i++)
    {
        int * arr1 = generateRandomArray(maxLen, maxValue, arr1Len); // 产生随机数组
        int * judgeArr = copyArray(arr1, arr1Len); // 备份数组
        insertSort(arr1, arr1Len); // 自己的排序算法
        sort(judgeArr, judgeArr + arr1Len); // STL库的sort排序算法
        if(!isEqual(arr1, arr1Len, judgeArr, arr1Len)) // 逐一比对二者排序结果
        {
            succeed = false;
            printArray(arr1, arr1Len);
            printArray(judgeArr, arr1Len);
            break;
        }

        arr1Len = 0;
        delete arr1;
        delete judgeArr;
    }
    cout << (succeed ? "Nice!" : "Oh no! Bug!!!") << endl;

    int arrLen = 0;
    int * arr = generateRandomArray(maxLen, maxValue, arrLen);  // 生成打印一个样本测试案例
    printArray(arr, arrLen);
    insertSort(arr, arrLen);
    printArray(arr, arrLen);
    delete arr;

    return 0;
}

测试结果:

-----调用insertSort实现插入排序-----
Nice!
-158 147 862 -212 -851 160 349 132 -969 -296 405 -370 -361
-969 -851 -370 -361 -296 -212 -158 132 147 160 349 405 862
  1. 随机数组产生的改进
    之前随机数组只是产生一个正整数[0, N]的随机数组,将它改进成产生一个正负数[-N, N]皆有的随机数组。
// 动态创建随机数组,数组长度和数值大小皆随机
int* generateRandomArray(int maxLen, int maxValue, int& len)
{
    // getRandom() [0, 1)
    // getRandom() * N [0, N)
    // (int)(getRandom() * N) [0, N - 1]
    len = (int)(getRandom() * maxLen);
    int* arr = new int[len];  
    for(int i = 0; i < len; i++)
    {
        // [-?, +?]
        arr[i] = (int)((maxValue + 1) * getRandom()) - (int)(maxValue * getRandom());
    }

    return arr;
}
  1. 逐一比对函数
// 逐一判断两个数组元素是否相等
bool isEqual(int arr1[], int arr1Len, int arr2[], int arr2Len)
{
    if((arr1 == NULL && arr2 != NULL) || (arr1 != NULL && arr2 == NULL))
    {
        return false;
    }
    if(arr1 == NULL && arr2 == NULL)
    {
        return true;
    }
    if(arr1Len != arr2Len)
    {
        return false;
    }
    for(int i = 0; i < arr1Len; i++)
    {
        if(arr1[i] != arr2[i])
        {
            return false;
        }
    }
    return true;
}

3.2 STL库vector容器实现

vector容器自带了许多有关数据处理的算法和迭代器,提高了code效率。
0. 主程序

int main(int args, char** argv)
{
    int maxLen = 20;
    int maxValue = 50;
    int testTime = 100;
    bool succeed = true;

    vector<int> arr1;
    vector<int> judgeArr;
    cout << "-----调用STL库vector容器实现插入排序-----" << endl;
    for(int i = 0; i < testTime; i++)
    {
        generateRandomArray(maxLen, maxValue, arr1);  // 生成随机数组
        judgeArr.resize(arr1.size()); // 对数数组重设大小
        copy(arr1.begin(), arr1.end(), judgeArr.begin()); // 拷贝数组到对数数组
        insert_sort(arr1);  // 自定义排序
        sort(judgeArr.begin(), judgeArr.end()); // STL排序

        if(judgeArr != arr1)
        {
            succeed = false;
            printVector(arr1);
            printVector(judgeArr);
            break;
        }
    }
    cout << (succeed ? "Nice!" : "Oh no! Bug!!!") << endl;

    generateRandomArray(maxLen, maxValue, arr1);
    printVector(arr1);
    insert_sort(arr1);
    printVector(arr1);

    return 0;
}

测试结果:

-----调用STL库vector容器实现插入排序-----
Nice!
47 5 25 -1 -41 12 37 -1 -26
-41 -26 -1 -1 5 12 25 37 47
  1. 随机数组产生的改进(vector容器实现)
    在一维数组的基础上引入了vector容器,更加符合C++特性。
// 动态创建随机数组,数组长度和数值大小皆随机
template<typename T>
bool generateRandomArray(int maxLen, int maxValue, vector<T>& arr)
{
    // getRandom() [0, 1)
    // getRandom() * N [0, N)
    // (int)(getRandom() * N) [0, N - 1]
    int len = 0;
    do{
        len = (int)(getRandom() * maxLen);
    }while(len < 2);
    vector<int>().swap(arr);
    arr.resize(len);
    for(int i = 0; i < arr.size(); i++)
    {
        arr[i] = (int)((maxValue + 1) * getRandom()) - (int)(maxValue * getRandom());
    }

    return true;
}

利用上述程序可套用其他排序算法,方法一样,可自行尝试。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值