归并排序

165 阅读1分钟

1. 合并算法

归并排序最核心的思路是,两个有序列表合并,只需要各循环一次,就可以将两个有序列表合并成一个有序列表。比如[1,4]和[2,3],1和2比较,将1放在temp数组中,4和2比较,将2放在temp中,4和3比较,将3放在temp中,最后将4放在temp中

先写合并的算法。

function merge(li, start, mid, end) {
    let left = start,
        right = mid + 1,
        tempList = [];
    while (left <= mid && right <= end) {
        if (li[left] < li[right]) {
            tempList.push(li[left]);
            left++;
        } else {
            tempList.push(li[right]);
            right++;
        }
    }
    while (left <= mid) {
        tempList.push(li[left]);
        left++;
    }
    while (right <= end) {
        tempList.push(li[right]);
        right++;
    }
    for (let index = 0; index < tempList.length; index++) {
        li[start + index] = tempList[index]
    }
}

2. 拆分

这里有一个前提就是,两个数组必需是有序数组,所以需要将原数组拆分,最终分成只有一个元素的时候,自然就是有序的,然后再逐层将数组合并。

function merge(li, start, mid, end) {
    let left = start,
        right = mid + 1,
        tempList = [];
    while (left <= mid && right <= end) {
        if (li[left] < li[right]) {
            tempList.push(li[left]);
            left++;
        } else {
            tempList.push(li[right]);
            right++;
        }
    }
    while (left <= mid) {
        tempList.push(li[left]);
        left++;
    }
    while (right <= end) {
        tempList.push(li[right]);
        right++;
    }
    for (let index = 0; index < tempList.length; index++) {
        li[start + index] = tempList[index]
    }
}

function mergeSort(li, start, end) {
    if (start < end) {
        let mid = Math.floor((start + end) / 2);
        mergeSort(li, start, mid);
        mergeSort(li, mid + 1, end);
        merge(li, start, mid, end);
    }
    return li;
}

let testLi = new Array(99);
for (let index = 0; index < testLi.length; index++) {
   testLi[index] = Math.ceil(Math.random() * 100)
}
console.log(testLi);
mergeSort(testLi, 0, testLi.length - 1)
console.log(testLi);

3.算法分析

归并算法时间复杂度为O(nlogn),而且和原数组的顺序没有关系,所以时间复杂度很稳定,空间复杂度为O(n)