如何让数组元素无序排列?
刚开始我也有些蒙,只想到了用Random产生一个随机整数rd,再让数组元素向前移动rd个位置。但这种方法却不是真的无序排列,明显能看出和原数组的排列的关系,也就没有达到目的。
明显需要转变思路,可以从日常生活中的挑苹果得到经验。怎么随机从篮子里挑一个苹果,然后再放回去,再次挑一个苹果,而苹果外形都差不多,要保证此次挑出的苹果不是上一次挑过的苹果,这要怎么做到?我们可以在挑过的苹果上打一个标签,下次再挑一个苹果时,有意识地不去挑带有标签的苹果就是了。就这样重复多次,就能随机的挑出每个苹果。
1.先定义一个数组,再用Arrays工具类生成与此数组相同的副本
int nums[]={12,14,13,15,18,19,20}; //原数组
System.out.println("原数组是:"+Arrays.toString(nums));
int[] copiedNums = Arrays.copyOf(nums,nums.length) ; //副本数组
2.再定义一个与数组所有元素均不同的标签数字,这个数字是算一个关键点。
int countsDifferent=0; // 标签数字与数组元素不同的次数
int different=0; // 标签数字
Random rd= new Random();
outCycle: //外层循环标签
/**产生标签数字并验证
***/
while(true){
different=rd.nextInt(); // 产生一个标签数字
for(int num : copiedNums){
/**如标签数字与数组中任一元素相同,
* 则退出内层循环,继续产生新的标签数字,进行
* 下一次外层循环,即再次进行些内层循环中
**/
if(different == num ){
break;
/**如标签数字与数组中任一元素不同,
* 标签不同次数变量则加1,当countsDifferent等于
* 数组长度时,则表明标签数字与数组所有元素都不同。
* 此时退出外层循环,即整个二重循环体结束。标签数字
* 达的值达到了设计目的。
**/
}else{
countsDifferent++;
if(countsDifferent>=copiedNums.length){
break outCycle;
}
}
}
}
3.将副本数组的随机位置的一个不为different元素赋值给原数组的一元素,并将副本中的这一元素赋值为different标签数字。按此规律遍历数组。
int index =0; //副本数组的随机索引
for(int i=0 ;i< nums.length; i++)
{
while(true)
{
/***生成副本数组的随机索引
* 这时需要注意,我们需要0至nums.length-1范围
* 的索引值。而Random的nextInt(int bound)方法,产生的是
* [0,bound)范围的随机数,并不包括bound值,即此方法生成的
* 是0至(bound-1)范围的数字。
* 因边界因素,方法里的参数是num.length而不是num.lengh-1 。
***/
index = rd.nextInt(nums.length);
if(copiedNums[index] != different)
{
nums[i]=copiedNums[index]; //随机位置的副本元素赋值给原数组
/***
*将获取过的副本元素赋值为标签数字,以保证下一次获取的随机位置的副本元素不会
* 取到此元素。
**/
copiedNums[index]= different;
/***
*原数组每在副本数组中新得一个非different值的随机位置的元素,则退出内层
*循环,进行下一次外层循环,对下一索引的原数组元素赋值。
**/
break;
}
}
}
System.out.println("无序后的数组:"+Arrays.toString(nums));