4.【入门】对数器

本文的网课内容学习自B站左程云老师的算法详解课程,旨在对其中的知识进行整理和分享~

网课链接:算法讲解005【入门】对数器-验证的重要手段_哔哩哔哩_bilibili

一、概念

  • 定义
    • 在算法学习和验证中,对数器是一种用于检验自己编写的算法是否正确的工具。通常用于比较自己实现的算法(比如排序算法、查找算法等)和已知正确的算法(例如标准库中的算法)的结果是否一致。
  • 作用原理
    • 对数器会生成多组随机测试数据,然后分别用自己编写的算法和正确的算法对这些数据进行处理,最后对比两组结果。如果对于大量的随机测试数据,两组结果都相同,那么就有较大的把握认为自己编写的算法是正确的。

二、实现步骤(以检验自定义排序算法为例)

  • 生成随机测试数据
    • 在很多编程语言中,可以使用随机数生成函数来创建随机的数组。例如在Java中,可以使用java.util.Random类来生成随机数填充数组。
    • 代码示例(Java):
import java.util.Random;

public class LogarithmChecker {
    public static int[] generateRandomArray(int n) {
        int[] arr = new int[n];
        Random random = new Random();
        for (int i = 0; i < n; i++) {
            arr[i]=random.nextInt(100);
        }
        return arr;
    }
}
  • 调用自己编写的算法和正确算法(如Java中的Arrays.sort)
    • 假设我们自己编写了一个排序算法mySort。
    • 代码示例(Java):
import java.util.Arrays;

public class LogarithmChecker {
    // 假设这是自己编写的排序算法
    public static void mySort(int[] arr) {
        // 这里是排序算法的具体实现
    }

    public static boolean checkSort() {
        int testTimes = 100;
        int maxSize = 100;
        int maxValue = 100;
        for (int i = 0; i < testTimes; i++) {
            int[] arr1 = generateRandomArray(maxSize);
            int[] arr2 = arr1.clone();
            mySort(arr1);
            Arrays.sort(arr2);
            boolean equal = true;
            for (int j = 0; j < arr1.length; j++) {
                if (arr1[j]!= arr2[j]) {
                    equal = false;
                    break;
                }
            }
            if (!equal) {
                return false;
            }
        }
        return true;
    }
}

三.举例说明(用于测试自己写的insertionSort函数是否正确)

算法原理

一、总体思路
  • 目标:这段代码主要是实现了插入排序算法,并通过与Java内置的Arrays.sort函数对比来验证自己实现的插入排序算法的正确性。同时,代码还包含了一些用于生成随机数组、复制数组、比较数组是否相等以及打印数组的辅助函数。
二、插入排序(insertionSort)原理
  • 首先进行边界条件判断,如果数组为空或者长度小于2,直接返回,因为长度小于2的数组本身就是有序的。
  • 外层循环for(int i = 1; i < arr.length; i++):从数组的第二个元素(索引为1)开始,逐步将每个元素插入到已排序的部分中。这里假设0 ~ i - 1的部分已经是有序的,现在要将arr[i]插入到合适的位置。
  • 内层循环for(int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--):在已排序的部分(0 ~ i - 1)中,从后向前扫描。如果当前元素arr[j]大于下一个元素arr[j + 1],则交换这两个元素(通过swap函数),继续向前扫描,直到找到合适的位置使得arr[j] <= arr[j + 1]或者已经扫描到数组的开头(j = 0)。
三、辅助函数原理

    1.交换函数(swap):这个函数用于交换数组中的两个元素。它通过一个临时变量temp,将arr[i]arr[j]的值进行交换。

    2.内置排序比较函数(comparator)这个函数调用了Arrays.sort函数,它是Java内置的排序函数,这里将其作为一个标准来对比自己实现的排序算法的正确性。

    3.随机数组生成函数(generateRandomArray):这个函数用于生成一个随机长度和随机元素值的数组

  • 首先,通过(int) ((maxSize + 1) * Math.random())计算随机数组的长度,使得长度在0到maxSize之间(包含0)。
  • 然后,对于数组中的每个元素,通过(int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random())计算随机值,这个表达式的目的是生成一个在-maxValuemaxValue之间(包含两端)的随机整数。

    4.数组复制函数(copyArray):这个函数用于复制一个数组。它创建一个新的数组res,其长度与输入数组arr相同,然后将arr中的每个元素依次复制到res中。

    5.数组相等判断函数(isEqual)这个函数用于判断两个数组是否相等。

  • 首先进行一些边界情况判断,如两个数组一个为null一个不为null,则直接返回false;如果两个数组都为null,则返回true
  • 如果两个数组长度不同,则返回false
  • 最后,通过遍历数组中的每个元素,如果有任何一个元素不相等,则返回false;如果所有元素都相等,则返回true

    6.数组打印函数(printArray):这个函数用于打印数组中的元素。如果数组为null则直接返回,否则遍历数组并逐个打印元素,最后换行。

四、测试部分原理
  • main函数中:
    • 定义了测试次数testTime为5000000,数组最大长度maxSize为100,数组元素最大值maxValue为100。
    • 用一个布尔变量succeed来表示测试是否成功,初始化为true
    • 通过一个大循环进行多次测试,每次测试:
      • 生成一个随机数组arr1,然后复制一份得到arr2
      • arr1使用自己实现的插入排序insertionSort,对arr2使用内置的排序函数comparator
      • 如果arr1arr2不相等(通过isEqual函数判断),则将succeed设置为false并跳出循环。
    • 最后根据succeed的值打印测试结果。然后再生成一个随机数组并进行排序,打印原始数组和排序后的数组。

代码实现

package com.itheima.demo;
​
import java.util.Arrays;
​
public class demo
{
    public static void insertionSort(int[] arr)
    {
        if(arr == null || arr.length < 2)
        {
            return;
        }
        // 0~0 有序的
        // 0~i 想有序
        for(int i = 1; i < arr.length; i++)
        {
            // 0~i做到有序
            for(int j = i-1; j >= 0 && arr[j] > arr[j+1]; j--)
            {
                swap(arr,j,j+1);
            }
        }
    }
​
    public static void swap(int[] arr, int i, int j)
    {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
​
​
    //电脑内置的排序函数
    public static void comparator(int[] arr)
    {
        Arrays.sort(arr);
    }
​
​
​
​
    //生成一个随机数组
    public static int[] generateRandomArray(int maxSize, int maxValue)
    {
        //Math.random() -> [0,1) 所有的小数,等概率返回一个
        //Math.random() * N -> [0,N) 所有小数,等概率返回一个
        //(int)(Math.random() *N) -> [0,N-1] 所有的整数,等概率返回一个
​
​
        int[] arr = new int[(int) ((maxSize + 1) * Math.random())];// 长度随机
        for(int i = 0; i < arr.length; i++)
        {
            arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
        }
        return arr;
    }
​
    //复制数组
    public static int[] copyArray(int[] arr)
    {
        if(arr == null)
        {
            return null;
        }
        int[] res = new int[arr.length];
        for(int i = 0; i < arr.length; i++)
        {
            res[i] = arr[i];
        }
        return res;
    }
​
​
    //判断结果是否相等
    public static boolean isEqual(int[] arr1, int[] arr2)
    {
        if((arr1 == null && arr2 !=null) || (arr1 != null && arr2 == null))
        {
            return false;
        }
        if(arr1 ==null && arr2 == null)
        {
            return true;
        }
        if(arr1.length != arr2.length)
        {
            return false;
        }
        for(int i = 0; i < arr1.length; i++)
        {
            if(arr1[i] != arr2[i])
            {
                return false;
            }
        }
        return true;
    }
​
​
​
    //打印数组
    public static void printArray(int[] arr)
    {
        if(arr == null)
        {
            return;
        }
        for(int i = 0; i < arr.length; i++)
        {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }
​
​
​
    //测试样例
    public static void main(String[] args)
    {
        int testTime = 5000000;
        int maxSize = 100;
        int maxValue = 100;
        boolean succeed = true;
        for(int i = 0; i < testTime; i++)
        {
            int[] arr1 = generateRandomArray(maxSize, maxValue);
            int[] arr2 = copyArray(arr1);
            insertionSort(arr1);//自己写的函数(用来测试)
            comparator(arr2);//已经确定正确的函数(用来对比)
            if(!isEqual(arr1, arr2))
            {
                succeed = false;
                break;
            }
        }
        System.out.println(succeed ? "Nice!" : "Fucking fucked!");
​
        int[] arr = generateRandomArray(maxSize, maxValue);
        printArray(arr);
        insertionSort(arr);
        printArray(arr);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值