(算法)归并、快速排序

91 阅读1分钟

分治

分而治之,其本质就是将一个大问题分解为若干个子问题,针对子问题分别求解后,再将子问题的解整合。

归并排序

分解子问题、求解每个子问题、合并子问题的解,得出大问题的解。

编码:

const mergeSort = (arr) => {
    const len = arr.length;
    
    if(len <= 1) return arr;
    
    const mid = Math.floor(len);
    const leftArr = mergeSort(arr.slice(0, mid));
    const rightArr = mergeSort(arr.slice(mid, len));
    arr = mergeArr(leftArr, rightArr);
    
    return arr;
}

const mergeArr(arr1, arr2){
    let i = 0, j = 0;
    const res = [];
    while(i < arr1.length && j < arr2.length){
        if(arr[i] < arr2[j]){
            res.push(arr[i]);
            i++;
        }else{
            res.push(arr2[j]);
            j++;
        }
    }
    if(i < arr1.length){
        // arr2此时已遍历完
        return res.concat(arr1.slice(i));
    }else{
        return res.concat(arr2.slice(j));
    }
}

规则:

对数组的分割排序、最后合并有序数组。

快速排序

快速排序在基本思想上和归并排序是一致的,区别在于快速排序并不会把真的数组分割开来再合并到一个新数组中去,而是直接在原有的数组内部进行排序。

编码:

const quickSort = (arr, left=0, right=arr.length - 1) => {
    if(arr.length > 1){
        const lineIndex = partition(arr, left, right);
        if(left < lineIndex - 1){
            quickSort(arr, left, lineIndex - 1);
        }
        
        if(lineIndex < right){
            quickSort(arr, lineIndex, right);
        }
    }
    return arr;
}

const partition = (arr, left, right) = > {
    //取中间位置值作为基准值
    const pivotValue = arr[Math.floor(left + (right - left)/2);
    
    let i = left, j = right;
    while(i<=j){
        while(arr[i] < pivotValue){
            i++;
        }
        
        while(arr[j] > pivotValue){
            j--;
        }
        
        if(i<=j){
            //交换
            [arr[i], arr[j]] = [arr[j], arr[i]];
            i++;
            j--;
        }
    }
    
    return i;
}

规则:

快速排序会将原始的数组筛选成较小和较大的两个子数组,然后递归地排序两个子数组。