JavaScript数组(一)——排序

吃可爱长大的小学妹 提交于 2020-03-01 03:11:31

JavaScript数组中有一个reverse()方法,可用于反转数组,如下代码所示:

var arr = [0, 1, 2, 3];
arr.reverse();
console.log(arr);//[3, 2, 1, 0]

但是多数情况下这并不能满足开发的需求,真实的情况往往是降序或升序排列。对数组进行排序很自然地会想到冒泡排序算法,下面我们来看一个例子:

var arr = [8, 1, 35, 3, 10];

// 冒泡排序 升序
function bubbleSort(arr){
  var temp;
  for(var i = 0; i < arr.length; i++){
    for(var j = i + 1; j < arr.length; j++){
      if(arr[i] > arr[j]){
        temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
      }
    }
  }
  return arr;
}

console.log(bubbleSort(arr));//[1, 3, 8, 10, 35]

这段代码有两个for循环,实现的思路是用外层循环依次取出每个元素,用内层循环和剩下的元素进行比较,如果取出的这个数较大,就与较小的数交换位置,这样一轮内循环结束,最小的数就成了第一个元素,依次第二小的数成为第二个元素...。用下面这幅图可以帮助理解:

如图所示,i = 0时,取出数组的第一个元素,和之后的每个元素比较,如果大于后面的元素就交换位置,这样当j14结束时,数组的第一个元素就是最小的元素。相似的,i = 1时,取出的是数组的第二个元素,依次和后面的每个元素比较,当j24结束时,数组的第二个元素就是第二小的元素。

从比较的过程也容易计算出比较的次数:

4 + 3 + 2 + 1 = n(n + 1) / 2 = (arr.length - 1)arr.length / 2 = 10

另一种思路是把相邻的两个元素进行比较,如果前者较大就交换二者的位置,这样一轮内循环结束后,最大的元素就是数组的最后一个元素,如下例所示:

function bubbleSort2(arr){
  var temp;
  for(var i = 0; i < arr.length - 1; i++){
    for(var j = 0; j < arr.length - 1 - i; j++){
      if(arr[j] > arr[j + 1]){
        temp = arr[j];
        arr[j] = arr[j + 1];
        arr[j + 1] = temp;
      }
    }
  }
  return arr;
}
console.log(bubbleSort2(arr));//[1, 3, 8, 10, 35]

同样画一个图来表示:

i = 0时,j03循环,依次比较相邻的两个数,前者大就交换,这样最大的数就像冒泡一样冒到了最后;i = 1时,第二大的数冒到了倒数第二的位置。

同样也容易计算出比较的次数:

4 + 3 + 2 + 1 = n(n + 1) / 2 = (arr.length - 1)arr.length / 2 = 10

和第一种思路比较的次数是一样的,只是从过程来看,第二种思路更名副其实一些。

其实对于这种常用的升降排序,JavaScript给我们提供了一个更方便的方法:sort()

在默认情况下,sort()方法按升序排列数组元素,为了实现排序,sort()方法会调用每个元素的toString()转型方法,然后比较得到的字符串,以确定如何排序。即使数组的每个元素都是数值,sort()方法比较的也是字符串,如下所示:

arr.sort();
console.log(arr);//[1, 10, 3, 35, 8]

如结果所示,按照字符串顺序'10'排在'1'的后面,'3'排在'10'的后面,'8'是最大的排在最后。显然这并不是我们希望的结果,因此,sort()方法可以接收一个比较函数作为参数,以便我们指定哪个值位于哪个值前面。看下面的示例:

function compare(v1, v2){
  if(v1 < v2){
     return -1;
  }else if(v1 > v2){
     return 1;
  }else{
     return 0;
  }
}

arr.sort(compare);
console.log(arr);//[1, 3, 8, 10, 35]

如代码所示,声明一个compare比较函数,它接收两个参数。compare传递给sort方法时,参数可以映射到数组的元素,如果第一个参数应该位于第二个参数之前则返回一个负数,如果两个参数相等则返回0,如果第一个参数应该位于第二个参数之后则返回一个正数。这里当v1 < v2时返回-1,也就是v1 < v2时,v1应该位于v2之前,即升序。

当然如果想降序排列也很容易,只要改变返回值就好了,-1改为11改为-1,如下所示:

function compare(v1, v2){
  if(v1 < v2){
     return 1;
  }else if(v1 > v2){
     return -1;
  }else{
     return 0;
  }
}

arr.sort(compare);
console.log(arr);//[35, 10, 8, 3, 1]

因为起关键作用的是返回值的正负与否,所以也可以使用下面这样更简化的方式:

//升序
function ascSort(v1, v2) {
  return v1 - v2;
}
arr.sort(ascSort);
console.log(arr);//[1, 3, 8, 10, 35]

//降序
function descSort(v1, v2){
  return v2 - v1;
}
arr.sort(descSort);
console.log(arr);//[35, 10, 8, 3, 1]

总结一句就是如果只是想反转数组,可以使用reverse()方法,如果想对数组进行升序或降序排列,可以使用sort()方法。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!