JavaScript排序有什么东东?

你好同学,我是沐爸,欢迎点赞、收藏、评论和关注。

在JavaScript中,排序是处理数组时常见的需求之一。JS提供了多种排序方法和算法,这些方法和算法各有特点,适用于不同的场景。

一、JS内置排序方法

sort()方法是数组对象的一个方法,用于对数组的元素进行排序,并返回排序后的数组。默认情况下,sort()方法将元素转换为字符串,并按照字符串的Unicode码点进行排序。注意:sort()排序会改变原数组。

自定义排序

可以通过提供一个比较函数作为sort()方法的参数来实现自定义排序。比较函数定义了排序的规则,它接收两个参数,并返回一个用于表示这两个参数排序顺序的数字。

  • 如果返回值小于0,那么第一个参数会被排在第二个参数之前。
  • 如果返回值等于0,那么两个参数的位置不变。
  • 如果返回值大于0,那么第一个参数会被排在第二个参数之后。

在JavaScript中,Array.prototype.sort() 方法可以对数组进行排序,无论是字符串数组、数字数组还是对象数组。对于对象数组,你需要提供一个比较函数来指定按哪个属性进行排序。下面是一些使用sort()排序的常见情形:

1. 默认排序行为

如果不提供比较函数,sort()方法会将数组元素转换为字符串,并按照字符串的Unicode码点进行排序。这通常不是数字数组所期望的排序方式。

let numbers = [3, 1, 4, 1, 5, 9];  
numbers.sort(); // 注意:这会按字符串排序,而不是数字  
console.log(numbers); // 输出可能是 ["1", "1", "3", "4", "5", "9"]

2.字符串数组排序

let fruits = ["Banana", "Orange", "Apple", "Mango"];  
fruits.sort();  
console.log(fruits); // 输出: ["Apple", "Banana", "Mango", "Orange"]

默认情况(未提供比较函数),按字符串的Unicode码点进行排序。

3.数字数组排序

对于数字数组,你需要提供一个比较函数来确保数字是按数值大小而不是字符串来排序的。

let numbers = [40, 100, 1, 5, 25];  
numbers.sort(function(a, b) {  
    return a - b;  // 正序:从小到大
    // return b - a;  // 倒序:从大到小
});  
console.log(numbers); // 输出: [1, 5, 25, 40, 100]

4.对象数组按属性排序

假设你有一个对象数组,并希望根据对象的某个属性进行排序。

let items = [  
    { name: "Edward", value: 21 },  
    { name: "Sharpe", value: 37 },  
    { name: "And", value: 45 },  
    { name: "The", value: -12 },  
    { name: "Magnetic", value: 13 },  
    { name: "Zeros", value: 37 }  
];  
  
// 按 value 属性升序排序  
items.sort(function(a, b) {  
    return a.value - b.value;  
});  
  
console.log(items);  
/* 输出:  
[  
  { name: 'The', value: -12 },  
  { name: 'Edward', value: 21 },  
  { name: 'Magnetic', value: 13 },  
  { name: 'Sharpe', value: 37 },  
  { name: 'Zeros', value: 37 },  
  { name: 'And', value: 45 }  
]  
*/  
  
// 如果要按 name 属性升序排序(注意:这里可能需要更复杂的比较逻辑来处理非ASCII字符)  
items.sort(function(a, b) {  
    let nameA = a.name.toUpperCase(); // 忽略大小写  
    let nameB = b.name.toUpperCase(); // 忽略大小写  
    if (nameA < nameB) {  
        return -1;  
    }  
    if (nameA > nameB) {  
        return 1;  
    }  
    // 如果 name 相同,则按 value 排序  
    return a.value - b.value;  
});  
  
console.log(items);  
/* 输出可能会根据 value 的不同而有所变化,但 name 会按字典序排序 */

注意:在按对象属性排序时,确保你的比较函数能够正确处理所有可能的情况,包括相等的情况(return 0;)和无法直接比较的情况(比如,当属性值类型不同时)。在上面的例子中,如果 name 属性相同,则按 value 属性进行次级排序。这是通过在 name 比较相等时返回 a.value - b.value 来实现的。然而,在实际应用中,你可能需要根据具体情况调整这个逻辑。

5.排序后保持原数组不变

sort()方法会就地(in-place)对数组进行排序,即直接修改原数组,而不是返回一个新数组。如果你需要保留原数组的顺序,可以先对数组进行浅拷贝。

let originalArray = [3, 1, 4, 1, 5, 9];  
let sortedArray = [...originalArray].sort((a, b) => a - b);  
console.log(originalArray); // 输出原数组的顺序  
console.log(sortedArray); // 输出排序后的数组

6.使用箭头函数简化比较函数

在ES6及更高版本中,可以使用箭头函数来简化比较函数的写法。

let numbers = [40, 100, 1, 5, 25];  
numbers.sort((a, b) => a - b);

let items = [  
    { name: "Edward", value: 21 },  
    { name: "Sharpe", value: 37 },  
    { name: "And", value: 45 },  
    { name: "The", value: -12 },  
    { name: "Magnetic", value: 13 },  
    { name: "Zeros", value: 37 }  
];   
// 按 value 属性升序排序  
items.sort((a, b) => a.value - b.value);

二、常见排序算法

除了sort()方法外,JS中还可以实现多种排序算法,这些算法在性能、稳定性、空间复杂度等方面各有差异。

冒泡排序(Bubble Sort)
  • 基本思想:通过重复遍历要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。遍历数列的工作是重复进行的,直到没有再需要交换的元素为止。
  • 时间复杂度:O(n^2)
  • 空间复杂度:O(1)
  • 稳定性:稳定
function bubbleSort(arr) {  
    let n = arr.length;  
    let swapped;  
    do {  
        swapped = false;  
        for (let i = 1; i < n; i++) {  
            if (arr[i - 1] > arr[i]) {  
                // 交换元素  
                let temp = arr[i - 1];  
                arr[i - 1] = arr[i];  
                arr[i] = temp;  
                swapped = true;  
            }  
        }  
        // 减少n的值,因为每一轮至少有一个元素被放到了正确的位置  
        n -= 1;  
    } while (swapped);  
    return arr;  
}  
  
let arr = [64, 34, 25, 12, 22, 11, 90];  
console.log(bubbleSort(arr));

选择排序(Selection Sort)
  • 基本思想:首先在未排序序列中找到最小(或最大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(或最大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
  • 时间复杂度:O(n^2)
  • 空间复杂度:O(1)
  • 稳定性:不稳定
function selectionSort(arr) {  
    let n = arr.length;  
    for (let i = 0; i < n - 1; i++) {  
        let minIndex = i;  
        for (let j = i + 1; j < n; j++) {  
            if (arr[j] < arr[minIndex]) {  
                minIndex = j;  
            }  
        }  
        // 交换找到的最小元素与当前位置的元素  
        let temp = arr[minIndex];  
        arr[minIndex] = arr[i];  
        arr[i] = temp;  
    }  
    return arr;  
}  
  
let arr = [64, 25, 12, 22, 11];  
console.log(selectionSort(arr));

插入排序(Insertion Sort)
  • 基本思想:将数组分为已排序和未排序两部分,每次从未排序部分取出一个元素,与已排序部分的元素进行比较,找到合适的位置并插入。
  • 时间复杂度:平均和最坏情况为O(n^2),最好情况为O(n)
  • 空间复杂度:O(1)
  • 稳定性:稳定
function insertionSort(arr) {  
    let n = arr.length;  
    for (let i = 1; i < n; i++) {  
        let key = arr[i];  
        let j = i - 1;  
  
        /* 将arr[i]插入到arr[0...i-1]中已排序的序列中 */  
        while (j >= 0 && arr[j] > key) {  
            arr[j + 1] = arr[j];  
            j = j - 1;  
        }  
        arr[j + 1] = key;  
    }  
    return arr;  
}  
  
let arr = [12, 11, 13, 5, 6];  
console.log(insertionSort(arr));

快速排序(Quick Sort)
  • 基本思想:选择一个基准元素,通过一趟排序将待排记录分隔成独立的两部分,其中一部分的所有记录均比另一部分的所有记录小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
  • 时间复杂度:平均情况为O(n log n),最坏情况为O(n^2)
  • 空间复杂度:O(log n)(递归栈空间)
  • 稳定性:不稳定
function quickSort(arr) {  
    if (arr.length <= 1) return arr;  
    let pivot = arr[Math.floor(arr.length / 2)];  
    let left = [];  
    let right = [];  
  
    for (let i = 0; i < arr.length; i++) {  
        if (arr[i] < pivot) left.push(arr[i]);  
        else if (arr[i] > pivot) right.push(arr[i]);  
    }  
  
    return [...quickSort(left), pivot, ...quickSort(right)];  
}  
  
let arr = [10, 7, 8, 9, 1, 5];  
console.log(quickSort(arr));

归并排序(Merge Sort)
  • 基本思想:将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。
  • 时间复杂度:O(n log n)
  • 空间复杂度:O(n)
  • 稳定性:稳定
function mergeSort(arr) {  
    if (arr.length < 2) return arr;  
  
    let middle = Math.floor(arr.length / 2);  
    let left = arr.slice(0, middle);  
    let right = arr.slice(middle);  
  
    return merge(mergeSort(left), mergeSort(right));  
}  
  
function merge(left, right) {  
    let result = [];  
    while (left.length && right.length) {  
        if (left[0] <= right[0]) {  
            result.push(left.shift());  
        } else {  
            result.push(right.shift());  
        }  
    }  
  
    return [...result, ...left, ...right];  
}  
  
let arr = [38

三、排序算法的选择

在选择排序算法时,需要根据数据的规模、数据的初始状态、对稳定性的要求等因素进行综合考虑。例如,对于小规模数据或基本有序的数据,插入排序和冒泡排序可能更加高效;对于大规模数据,快速排序、归并排序等算法可能更加适合。

综上所述,JS中的排序涉及多个方面,包括内置的sort()方法以及多种排序算法。掌握这些排序方法和算法对于提高编程能力和解决实际问题具有重要意义。

好了,分享结束,谢谢点赞,下期再见。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沐爸muba

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值