数组的随机排序

文章目录

      • 1.数组的重排序
        • 1.1重排序方法
        • 1.2 reverse方法
        • 1.3 sort方法
      • 2.数组的随机排序
        • 2.1利用数组的sort方法
        • 2.2利用数组的splice方法
        • 2.3利用ES6解构赋值的变量交换(洗牌算法)

1.数组的重排序

1.1重排序方法

  • 数组中存在两个直接用来重排序的方法: reverse()sort()
  • reverse()用来反转数组项的顺序,sort()在默认情况下用来使数组项升序排列。

1.2 reverse方法

  • 直接反转数组项目的值,会改变原来数组的值。
    		/*正常情况*/
    		let arr = [1,0,5,9,6,7,2,4];
    		arr.reverse();
    		document.write(arr); //4,2,7,6,9,5,0,1
    

1.3 sort方法

不带参数:

  • 默认情况下,sort方法会将数组项按照升序排列,会改变原来的数组。
  • 原理:sort方法会调用每个数组项的toString()转型方法,两两比较确定排序,所以从本质上讲,不带参数的sort方法比较的是字符串。
  • 比较次数:sort方法对传入的参数进行两两比较,按照返回值决定是否交换两个数组项的位置。以升序为例,第一轮比较结束,数组项中最大值会在最后的位置,第二轮数组项中第二大的值会在倒数第二的位置,以此类推。不同数组使用sort方法进行排序时,两两参数比较次数因数组而异。
  • 由于比较的是字符串,所以5和10比较,虽然数值的5<10,但是字符串中10在5前面,所以这种排序并不能实现正确的升序功能,如下所示。
    		/*正常*/
    		let arr = [9,1,2,7,5,3];
    		arr.sort();
    		document.write(arr); //1,2,3,5,7,9
    
    		/*有问题*/
    		let arr = [1,2,10,5,15,21];
    		arr.sort();
    		document.write(arr); //1,10,15,2,21,5
    

带参数:

  • sort方法接收一个比较函数作为参数,以返回值正负决定排列次序。其中比较函数接收两个参数,如果第一个参数应该在第二个参数前面返回负数,否则返回正数,0表示不变。

    		/*数值类型升序比较*/
    		let arr = [1,2,10,5,15,21];
    		arr.sort((a,b)=>{
    			return a-b;
    		});
    		document.write(arr); //1,2,5,10,15,21
    
    		/*数值类型降序比较*/
    		let arr = [1,2,10,5,15,21];
    		arr.sort((a,b)=>{
    			return b-a;
    		});
    		document.write(arr); //21,15,10,5,2,1
    
  • 利用sort方法可以自定义比较函数的特点,如果比较函数中返回值的正负是随机的,那么交换的结果也会是随机的。

2.数组的随机排序

2.1利用数组的sort方法

  • 原理:数组的sort方法可以自定义比较函数,根据比较函数的返回值决定数组项的位置,当返回值是随机时,最后排序的结果也会是随机的。
  • 实现:使用Math.random()生成0-1之间的随机小数,然后与0.5相减,最后得到随机值,作为比较函数的返回值。
  • 特点:使用Math.random的得出随机结果,进行两两比较的结果只有两种,交换或者不变,所以随机性不高。
     		let arr = [1,7,2,5,9,4,3];
    		arr.sort((a,b)=>{
    			return (Math.random()-0.5);
    		});
    		document.write(arr); //结果随机
    

2.2利用数组的splice方法

  • 原理:数组的splice方法可以对数组进行删除、添加、替换数组项的操作,并返回删除的数组项,会改变原来的数组。当每一轮抽出的数组项在数组中是随机的,那么最后排列成的新数组就是原来数组的随机排序结果。
  • 实现:使用(Math.random()*arr.length)生成0-数组长度之间的随机小数,然后对随机小数进行向下取整,得到随机下标,作为本轮需要抽出的数组项,遍历的轮数为数组长度数。
  • 特点:遍历过程中每轮新的数组项都是随机出来的,相比第一种随机性更高,但是创建了新的数组,遍历过程需要对两个数组都进行访问和修改,空间复杂度也高于第一种。
    		let arr = [1,7,2,5,9,4,3];
    		let newArr = [];
    		let len = arr.length;
    		for(let i=0;i<len;i++){
    			let index = Math.floor((Math.random()*arr.length));
    			newArr.push(arr.splice(index,1));
    		}
    		document.write(newArr); //结果随机
    

2.3利用ES6解构赋值的变量交换(洗牌算法)

  • 原理:通过遍历数组,每次产生随机下标,随机下标的数组项与当前下标的数组项进行互换。
  • 实现:使用(Math.random()*arr.length)生成0-数组长度之间的随机小数,然后对随机小数进行向下取整,得到随机下标,使用ES6的解构赋值中的变量交换[x,y] = [y,x]实现随机下标的数组项与当前下标的数组项进行交换。
  • 特点:遍历过程的每一轮都实现随机,使用变量交换直接对原数组进行操作,不必访问新数组,减少空间复杂度。
    	 	let arr = [1,7,2,5,9,4,3];
    		let len = arr.length;
    		for(let i=0;i<len;i++){
    			let index = Math.floor((Math.random()*arr.length));
    			[arr[i],arr[index]] = [arr[index],arr[i]];
    		}
    		document.write(arr); //结果随机
    

你可能感兴趣的:(JavaScript)