对数器和异或运算

本文探讨了对数器在验证排序算法正确性中的作用,通过生成随机样本并进行对比测试,确保插入排序算法的实现与系统排序方法一致。同时,介绍了异或运算的性质,并展示了如何利用异或运算在不使用额外变量的情况下交换两个数,找出数组中出现奇数次的元素,以及提取整数最右侧的1。这些算法和技巧在实际编程中具有广泛应用价值。
摘要由CSDN通过智能技术生成

对数器和异或运算

对数器

什么是对数器?

  1. 你想要测的方法A
  2. 实现复杂度不好但是容易实现的方法B
  3. 实现一个随机样本产生器
  4. 把方法A和方法B跑相同的随机样本,看看得到的结果是否一样
  5. 如果有一个随机样本使得比对结果不一致,打印样本进行人工干预,改对方法A和方法B
  6. 当样本数量很多时比对测试依然正确,可以确定方法A已经正确。

代码

package com.cz.Sort;

import java.util.Arrays;

/**
 *  从第2个元素开始,和该元素之前的元素比较,将小的数一个一个送到前,一直往前面换
 * @ProjectName: Data_structure
 * @Package: com.cz.Sort
 * @ClassName: InsertSort  插入排序
 * @Author: 张晟睿
 * @Date: 2022/3/4 9:20
 * @Version: 1.0
 */
public class InsertSort {
    public static void main(String[] args) {
        int testTime = 500000;  //测试的次数
        int maxSize = 100;  //数组最大长度
        int maxValue = 100; //数组中的最大值
        boolean succeed = true; //判断是否测试成功
        for (int i = 0; i < testTime; i++) {
            //初始化
            int[] arr1 = generateRandomArray(maxSize, maxValue);
            //将方法generateRandomArray中的数值拷贝到数组2中,测试过程保证两个数组相同
            int[] arr2 = copyArray(arr1);
            //待测方法
            insertsort(arr1);
            //系统方法———100%正确
            comparator(arr2);
            if (!isEqual(arr1,arr2)) {
                succeed = false;
                break;
            }
        }
        System.out.println(succeed ? "Nice!" : "Fail!");
        int[] arr = generateRandomArray(maxSize, maxValue);
        printArray(arr);
        insertsort(arr);
        printArray(arr);
    }

    public static void insertsort(int arr[]){
        if (arr == null || arr.length < 2) {
            return;
        }
        for (int i = 1; i < arr.length; i++) {
            for (int j = i; j > 0 && arr[j-1] > arr[j]; j--) {
                //与相邻的元素比较 因为要把小的数一个一个弄到最前面
//                if (arr[j - 1] > arr[j]){
                    swap(arr, j-1 , j);
//                }
            }
        }
    }

    /**
     * 交换数组第 i 个和 第 j 个元素
     * @param arr 需要交换的数组
     * @param i 原来的位置
     * @param j 需要交换的位置
     */
    public static void swap(int arr[], int i, int j){
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    public static int[] generateRandomArray(int maxSize,int maxValue){
        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 + 1) * Math.random());
        }
        return arr;
    }

    public static void comparator(int[] arr) {
        Arrays.sort(arr);
    }

    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 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;
    }
}

异或运算

异或运算:相同为0,不同为1

同或运算:相同以1,不同为0

能长时间记住的概率接近0%,所以,异或运算就记成无进位相加

性质

  1. 0^N == N
  2. N^N == 0
  3. 异或运算满足交换律和结合率

练习

  1. 如何不用额外变量交换两个数
  2. 一个数组中有一种数出现了奇数次,其他数都出现了偶数次,怎么找到并打印这种数
  3. 怎么把一个int类型的数,提取出最右侧的1来
  4. 一个数组中有两种数出现了奇数次,其他数都出现了偶数次,怎么找到并打印这两种数

代码

package com.cz.Code_01;

/**
 * @ProjectName: Data_structure
 * @Package: com.cz.Code_01
 * @ClassName: EvenTimesOddTimes
 * @Author: 张晟睿
 * @Date: 2022/3/15 23:05
 * @Version: 1.0
 */
public class EvenTimesOddTimes {
    //交换两个数,不开辟新的空间
    public static void swap(int i, int j){
        i = i ^ j;
        j = i ^ j;
        i = i ^ j;
    }

    // arr中,只有一种数,出现奇数次
    public static void printOddTimesNum1(int[] arr) {
        int eor = 0;
        for (int i = 0; i < arr.length; i++) {
            eor = eor ^ arr[i];
        }
        System.out.println(eor);
    }

    //怎么把一个int类型的数,提取出最右侧的1来
    public static int rightOne(int nums){
        int eor = 0;
        int rightOne = eor & (~eor + 1); // 提取出最右的1
        return rightOne;
    }

    //一个数组中有两种数出现了奇数次,其他数都出现了偶数次,怎么找到并打印这两种数
    public static void printOddTwoTimesNum1(int[] arr) {
        int eor = 0;
        //找到出现了奇数次的这两种数字
        for (int i = 0; i < arr.length; i++) {
            eor ^= arr[i];
        }
        int rightone = eor & (~eor + 1);//找到二进制下第一个1出现的位置
        int Odd = 0;
        for (int i = 0 ; i < arr.length ; i++){
            if((arr[i] & rightone) != 0){
              Odd ^= arr[i];
            }
        }
        System.out.println(Odd + " " + (eor ^ Odd));
    }

    public static void main(String[] args) {
        int[] arr1 = { 3, 3, 2, 3, 1, 1, 1, 3, 1, 1, 1 };
        printOddTimesNum1(arr1);

        int[] arr2 = { 4, 3, 4, 2, 2, 2, 4, 1, 1, 1, 3, 3, 1, 1, 1, 4, 2, 2 };
        printOddTwoTimesNum1(arr2);

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

java厂长

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值