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

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

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

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

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

package com.test;

import java.util.Random;


public class TestArray {
 public static int runCount =0;//用于记录方法运算次数
 
 public int []  m1(int [] arr){
  Random ran = new Random();
  int length = arr.length;
  int [] newArr = new int[length];
  int count =0;
  while (true) {
   runCount ++;
   int r = ran.nextInt(length)+1;
   if(!exist(r, newArr)){
    newArr [count] = r;
    count++;
   }
   if(count==length){
    break;
   }
  }
  System.out.println("m1 运算次数  = "+runCount);
  return newArr;
 }
 
 public static boolean exist(int a,int [] arr){
  for (int i = 0; i < arr.length; i++) {
   if(arr[i] ==a){
    return true;
   }
  }
  return false;
 }



 

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

 //-----------------------------------------------
 public int []  m2(int [] arr){
  Random ran = new Random();
  int [] newArr = new int[arr.length];
  int k = 0;
  while (arr.length>0) {
   runCount++;
   int index = ran.nextInt(arr.length);//随即数组下标
   newArr[k++] = arr[index];
   arr = removeElement(arr[index], arr);
  }
  System.out.println("m2运算次数  = "+runCount);
  return newArr;
 }
 
 public int [] removeElement(int ele,int [] arr){
  int [] arr2 =new int[arr.length-1];
  int k = 0;
  for (int i = 0; i < arr.length; i++) {
   runCount++;
   if(arr[i]!=ele){
    arr2[k++] = arr[i];
   }
  }
  return arr2;
 }


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

 //-----------------------------------------------
 public int []  m3(int [] arr) {
  int [] arr2 =new int[arr.length];
  int count = arr.length;
  int cbRandCount = 0;// 索引
  int cbPosition = 0;// 位置
  int k =0;
  do {
   runCount++;
   Random rand = new Random();
   int r = count - cbRandCount;
   cbPosition = rand.nextInt(r); 
   arr2[k++] = arr[cbPosition];
   cbRandCount++;
   arr[cbPosition] = arr[r - 1];// 将最后一位数值赋值给已经被使用的cbPosition
  } while (cbRandCount < count);
  System.out.println("m3运算次数  = "+runCount);
  return arr2;
 }


测试下代码:

	// ----------------------------------------------

	public static void main(String[] args) {
		int[] arr = new int[10];
		for (int i = 0; i < arr.length; i++) {
			arr[i] = i + 1;
		}
		TestArray t = new TestArray();
		arr = t.m1(arr);
		print(arr);
		arr = t.m2(arr);
		print(arr);
		arr = t.m3(arr);
		print(arr);
	}

	public static void print(int[] arr) {
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i] + " ");
		}
		System.out.println();
		runCount = 0;
	}


结果:

m1 运算次数  = 51
3 10 2 1 5 9 6 8 4 7 
m2运算次数  = 65
1 3 8 2 10 5 9 6 7 4 
m3运算次数  = 10
10 7 8 3 1 5 6 9 2 4 


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

你可能感兴趣的:(java)