归并排序与快速排序

139 阅读2分钟

归并排序

性能分析

  • 时间复杂度:平均 O(nlogN)、最好 O(nlogN)、最坏 O(nlogN)
  • 空间复杂度:O(N) ,需要开启额外的数组来存合并后的数组,每次递归会释放上一层合并的结果,因此内存中同一时间只会保留一个数组,最长为n
  • 稳定,每次两个子数组中元素相等,都优先选择左边的元素,保证相等元素的先后顺序一致

思路分析

  • 数组不断二分,直到数组的长度为1
  • 合并两个有序子数组,直到构建出完整的排序数组
  • 合并之后的有序,是自底向上的排序
function merge(arr1, arr2) {
    const res = [];
    let index1 = 0;
    let index2 = 0;
    while (index1 < arr1.length && index2 < arr2.length) {
        if (arr1[index1] < arr2[index2]) {
            res.push(arr1[index1]);
            index1++;
        } else {
            res.push(arr2[index2]);
            index2++;
        }
    }
    const remain = 
        index1 < arr1.length ? arr1.slice(index1) : arr2.slice(index2);
    res.push(...remain);
    return res;
}

var sortArray = function(nums) {
    if (nums.length < 2) {
        return nums;
    }
    const mid = Math.floor(nums.length / 2);
    const arr1 = sortArray(nums.slice(0, mid));
    const arr2 = sortArray(nums.slice(mid));
    return merge(arr1, arr2);
};

快速排序

性能分析

  • 时间复杂度:平均 O(nlogN)、最好 O(nlogN)、最坏 O(n2),理想的情况每次都把数组分成小于基准和大于基准两侧的数据
  • 空间复杂度,快排没有额外的数组空间开销,空间复杂度由递归的深度决定,平均O(logN),最坏O(n)
  • 不稳定,一次分区操作中,等于基准值的数字相对位置可能发生改变
    • [1, 3, 3, 2, 2],分区最后pivotIndex = 1,因此变成[1, 2, 3, 3, 2],第二个索引的2原来在最后一个索引,两个2的相对顺序就发生了改变

思路分析

  • 每次取一个基准,把数组分成小于基准和大于基准两部分
  • 递归到最后,数组只剩两个元素,这两个元素就排好序了,整个数组也有序了
  • 是自顶向下的排序
function partition(nums, left, right) {
    let pivot = nums[right]; // 基准值
    let pivotIndex = left; // 分区指针
    // pivotIndex左边都是小于基准的值
    for (let i = left; i < right; i++) {
        if (nums[i] < pivot) {
            [nums[pivotIndex], nums[i]] = [nums[i], nums[pivotIndex]];
            pivotIndex++;
        }
    }
    // 把基准值放在中间,最后pivotIndex指向一个大于基准值的位置(或者等于right)
    [nums[pivotIndex], nums[right]] = [nums[right], nums[pivotIndex]];
    return pivotIndex;
}

function quickSort(nums, left, right) {
    if (left >= right) {
        return;
    }
    const pivotIndex = partition(nums, left, right);
    quickSort(nums, left, pivotIndex - 1);
    quickSort(nums, pivotIndex + 1, right);
}

var sortArray = function(nums) {
    quickSort(nums, 0, nums.length - 1);
    return nums;
};