0.排序相关辅助函数(重点:对数器)
1.简单排序的交换函数[位运算版]
(注意:位运算优先级较低,复合运算的时候需要加上小括号)
位运算一般较快.(但特殊情况自己与自己交换会变为0,如快排和堆排)
public static void swap(int[] arr, int i, int j) {
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
} 普通版:(辅助变量temp,适合所有场景,较慢)
public static void swap(int[] arr, int i, int j) {
int temp = arr[i] ;
arr[i] = arr[j];
arr[j] = temp;
} 加减版:(适合所有场景,中等,可能越界)
public static void swap(int[] arr, int i, int j) {
arr[i] = arr[i] + arr[j];
arr[j] = arr[i] - arr[j];
arr[i] = arr[i] - arr[j];
} 2.取两数的平均值,中间值mid
普通版:(相加除2)
mid=(left +right)/2;
优化版1:(减小了越界的可能性)
mid=left +(right-left)/2;
优化版2:(位运算)
//>>右移,带符号 >>>右移,无符号 右移一位相当于/2
//注意位移运算外面的小括号,因为位运算优先级低
//位运算相对较快
int mid = left + ((right - left) >> 1);
//heapInsert中直接使用位运算计算父节点,会出现负数-1,数组下边越界
//当index=0时,parent=(index-1)/2 ;【parent=0】 parrent=(index-1)>>1;【parent=-1】
//while(index>0&&a[index]>a[((index-1)>>1)]){ //此时需要加上index>0 3.复制数组
1.直接用java系统函数
<1>copyOf(int[], int))**(int[] original, int newLength)
复制指定的数组,截取或用 0 填充(如有必要),以使副本具有指定的长度。
<2>copyOfRange(int[] original, int from, int to)
将指定数组的指定范围复制到一个新数组。
2.自写copyArray()
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;
} 4.打印数组
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();
} 5.对数器
什么是对数器?
意义:
更快确定自写函数的正确性,直接输出错误用例,方便调试
方法:
1.写一个比较器,比较自写函数与绝对正确函数对数组处理后的结果;
2.比较次数、范围自定义后,数组长度随机,内部值随机(为方便调试,长度较小,次数多)
3.如果不同,返回false并打印不同的那次 原数组和自写函数排序后的数组
4.相同则返回true.因为次数足够多,样本量足够大,所以认为正确
对数器的概念和使用
0,有一个你想要测的方法a,
1,实现一个绝对正确但是复杂度不好的方法b,
2,实现一个随机样本产生器
3,实现比对的方法
4,把方法a和方法b比对很多次来验证方法a是否正确。
5,如果有一个样本使得比对出错,打印样本分析是哪个方法出错
6,当样本数量很多时比对测试依然正确,可以确定方法a已经正确。
比较器:比较两数组是否相等
<1>系统函数.equals
Arrays.equals(int[] a,int[] a2)
<2>自写比较
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 int[] generateRandomArray(int maxSize, int maxValue) {
//长度在自定义范围内随机
int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
//数值在自定义范围内随机;可0,负数,正数
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
}
return arr;
} 对数器使用:不同返回false和相应用例
int testTime = 500000;
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);
int[] arr3= copyArray(arr1);
bubbleSort(arr1);
comparator(arr2);
if (!isEqual(arr1, arr2)) {
succeed = false;
break;
}
if (succeed = false) {
//原数组,出错测试数据
printArray(arr3);
//排错"后数组
printArray(arr1);
//"绝对正确"数组"
printArray(arr2);
}
}
System.out.println(succeed ? "Nice!" : "***ing ***ed!"); 
京公网安备 11010502036488号