将一数组乱序排列的三种方法

 游戏中遇到这样的问题,需要将一组已知的数据打乱,按照以前和现在的做法,总结了以下方法。

方法一,最笨的菜鸟方法,也是容易想到的(幸好我没想过这种方法 :))

从已知数组中随机一个数,然后加入到另一个数组中,在加入之前,先检查是否已经加入过。

这种方法有很大运气成分,且数据越大,效率越低,超过一定数目,则程序几乎无法执行,会一直卡在那里,代码:

[java]  view plain copy
 
  1. package com.test;  
  2.   
  3. import java.util.Random;  
  4.   
  5.   
  6. public class TestArray {  
  7.  public static int runCount =0;//用于记录方法运算次数  
  8.    
  9.  public int []  m1(int [] arr){  
  10.   Random ran = new Random();  
  11.   int length = arr.length;  
  12.   int [] newArr = new int[length];  
  13.   int count =0;  
  14.   while (true) {  
  15.    runCount ++;  
  16.    int r = ran.nextInt(length)+1;  
  17.    if(!exist(r, newArr)){  
  18.     newArr [count] = r;  
  19.     count++;  
  20.    }  
  21.    if(count==length){  
  22.     break;  
  23.    }  
  24.   }  
  25.   System.out.println("m1 运算次数  = "+runCount);  
  26.   return newArr;  
  27.  }  
  28.    
  29.  public static boolean exist(int a,int [] arr){  
  30.   for (int i = 0; i < arr.length; i++) {  
  31.    if(arr[i] ==a){  
  32.     return true;  
  33.    }  
  34.   }  
  35.   return false;  
  36.  }  


 

方法二,这种方法是我遇到这个问题就想到的,思路就是:先随机出已知数组的下标值,然后取出这个数放到另一个数组中,再从已知数组中删除这个数。这种方法的运算次数是根据数组长度而定的,缺点是 大部分运算都耗在删除的判断上,主要是因为 数组不像list那样,能删除一个指定位置的值。代码:

[java]  view plain copy
 
  1. //-----------------------------------------------  
  2. public int []  m2(int [] arr){  
  3.  Random ran = new Random();  
  4.  int [] newArr = new int[arr.length];  
  5.  int k = 0;  
  6.  while (arr.length>0) {  
  7.   runCount++;  
  8.   int index = ran.nextInt(arr.length);//随即数组下标  
  9.   newArr[k++] = arr[index];  
  10.   arr = removeElement(arr[index], arr);  
  11.  }  
  12.  System.out.println("m2运算次数  = "+runCount);  
  13.  return newArr;  
  14. }  
  15.   
  16. public int [] removeElement(int ele,int [] arr){  
  17.  int [] arr2 =new int[arr.length-1];  
  18.  int k = 0;  
  19.  for (int i = 0; i < arr.length; i++) {  
  20.   runCount++;  
  21.   if(arr[i]!=ele){  
  22.    arr2[k++] = arr[i];  
  23.   }  
  24.  }  
  25.  return arr2;  
  26. }  


 方法三, 这种方法就很巧妙了,是在c 的代码中看到,翻译成了java代码,它的巧妙在于:每次从已知数组随机一个数,然后将数组的最后一个值 赋值给前面随机到的数的位置上,然后将长度-1,再从原数组下标-1的数组中随机。 运算次数就是数组长度,这种方法真的很聪明啊,以下是代码:

[java]  view plain copy
 
  1. //-----------------------------------------------  
  2. public int []  m3(int [] arr) {  
  3.  int [] arr2 =new int[arr.length];  
  4.  int count = arr.length;  
  5.  int cbRandCount = 0;// 索引  
  6.  int cbPosition = 0;// 位置  
  7.  int k =0;  
  8.  do {  
  9.   runCount++;  
  10.   Random rand = new Random();  
  11.   int r = count - cbRandCount;  
  12.   cbPosition = rand.nextInt(r);   
  13.   arr2[k++] = arr[cbPosition];  
  14.   cbRandCount++;  
  15.   arr[cbPosition] = arr[r - 1];// 将最后一位数值赋值给已经被使用的cbPosition  
  16.  } while (cbRandCount < count);  
  17.  System.out.println("m3运算次数  = "+runCount);  
  18.  return arr2;  
  19. }  


测试下代码:

[java]  view plain copy
 
  1. // ----------------------------------------------  
  2.   
  3. public static void main(String[] args) {  
  4.     int[] arr = new int[10];  
  5.     for (int i = 0; i < arr.length; i++) {  
  6.         arr[i] = i + 1;  
  7.     }  
  8.     TestArray t = new TestArray();  
  9.     arr = t.m1(arr);  
  10.     print(arr);  
  11.     arr = t.m2(arr);  
  12.     print(arr);  
  13.     arr = t.m3(arr);  
  14.     print(arr);  
  15. }  
  16.   
  17. public static void print(int[] arr) {  
  18.     for (int i = 0; i < arr.length; i++) {  
  19.         System.out.print(arr[i] + " ");  
  20.     }  
  21.     System.out.println();  
  22.     runCount = 0;  
  23. }  


结果:

[java]  view plain copy
 
  1. m1 运算次数  = 51  
  2. 3 10 2 1 5 9 6 8 4 7   
  3. m2运算次数  = 65  
  4. 1 3 8 2 10 5 9 6 7 4   
  5. m3运算次数  = 10  
  6. 10 7 8 3 1 5 6 9 2 4   


第三种方法还是值得学习的,大家如果有其它好的方法和思路欢迎补充~~

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值