算法—排序

202 阅读3分钟

冒泡算法

比较当前元素与下一个元素,大于则交换位置,每次循环结果,最大的元素向后排

const arr = [1, 20, 10, 30, 22, 11, 55, 24, 31, 88, 12, 100, 50];
function swap(arr,i,j){
    let temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}
function bubbleSort(arr){
    let len = arr.length;
    for(let i = 0;i < len-1;i++){
        for(let j = 0;j < len-i-1;j++){
            if(arr[j] > arr[j+1]){
                swap(arr,j,j+1)
            }
        }
    }
    return arr;
}

时间复杂度:平均时间复杂度是O(n^2)。由于辅助空间为常数,所以空间复杂度是O(1)。
改进,使其时间复杂度在大多数顺序的情况下减小到O(n):

function bubbleSort1(arr){
    let len = arr.length
    for(let i = 0;i < len-1;i++){
        let flag = false;
        for(let j = 0;j < len-i-1;j++){
            if(arr[j] > arr[j+1]){
                flag = true;
                swap(arr,j,j+1)
            }
        }
        if(!falg){
            break;
        }
    }
}
function bubbleSort2(arr){
    let len = arr.length;
    for(let i = len-1;i >= 0;i--){
        for(j = 0;j < i;j++){
            if(arr[j] > arr[j+1]){
                swap(arr,j,j+1);
            }
        }
    }
}

选择排序

每次循环选出最小元素排在前面

function selectionSort(arr){
    let len = arr.length;
    for(let i = 0;i < len-1;i++){
        lei index = i;
        for(let j = i+1;j < len;j++){
            if(arr[index] > arr[j]){
                index = j
            }
        }
        swap(arr,i,index)
    }
    return arr;
}

平均时间复杂度是O(n^2),是一个不稳定算法,因为每次交换之后都改变了后续数组的顺序。辅助空间是常数,空间复杂度是O(1)

插入排序

循环遍历每个元素,将其插入到已经排序好的数组中

function insertSort(arr){
    for(let i = 0;i < arr.length;i++){
        let temp = arr[i];
        for(let j = 0;j < i;j++){
            if(temp < arr[j] && j === 0){
                arr.splice(i,1);
                arr.shift(temp);
            }else if(arr[j] < temp && temp < arr[j+1] && j < i-1){
                arr.splice(i,1);
                arr.splice(j+1,0,temp);
            }
        }
    }
    return arr
}

平均时间复杂度是O(n^2)。辅助空间为常数,空间复杂度是O(1)

快速排序

选择一个基数,将小于基数的排到基数左边,大于基数的排到基数右边,之后递归左边和右边

function quickSort(arr){
    if(arr.length <= 1){
        return arr;
    }
    let temp = arr[0],left = [],right = [];
    for(let i = 1;i < arr.length;i++){
        if(arr[i] > temp){
            right.push(arr[i])
        }else{
            left.push(arr[i])
        }
    }
    return quickSort(left).concat([temp],quickSort(right))
}

时间复杂度低O(nlogn),性能好

归并排序

将数组等分成不同的小数组,小数组内部排序,然后合并等分内部排序,不断重复,直至排序完毕

function mergeSort(arr,seg = 1){
    let len = arr.length;
    if(seg > len){
        return arr;
    }
    let arrB = [];
    for(let start = 0;start < len;start += 2*seg){
        let mid = Math.min(start + seg,len),heig = Math.min(start + 2*reg,len);
        let start1 = start,end1 = mid,
            start2 = mid,end2 = heig;
        while(start1 < end1 && start2 < end2){
            arr[start1] < arr[start2] ? arrB.push(arr[start1++]) : arrB.push(arr[start2++]);
        }
        while(start1 < end1){
            arrB.push(arr[start1++]);
        }
        while(start2 < end2){
            arrB.push(arr[start2++])
        }
    }
    return mergeSort(arrB,seg * 2)
}

平均时间复杂度是O(nlogn)。辅助空间是n,空间复杂度是O(n)。

基数排序

依次对按照数的每一位(从低到高)进行排序,最终返回一个正常排序的数组

function radixSort(arr){
    let len = arr.length,dis = 0,maxNumb = Math.max(...arr);
    let count = new Array(10),tmp = new Array(len);
    while(maxNum >= 1){
        maxNum /= 10;
        dis++;
    }
    for(let i = 1,radix = 1;i <= dist;i++){
        for(let j = 0;j < 10;j++){
            count[j] = 0;
        }
        for(let j = 0;j < len;j++){
            let k = parseInt(arr[j]/radix)%10;
            count[k]++;
        }
        for(let j = 1;i < 10;j++){
            count[j] += count[j-1];
        }
        for(let j = len-1;j >= 0;j--){
            let k = parseInt(arr[j]/radix)%10;
            tmp[count[k]-1] = arr[j];
            count[k]--;
        }
        for(let j = 0;j < len;j++){
            arr[j] = tmp[j];
        }
        radix *= 10;
    }
    return arr;
}

平均时间复杂度是O(k*n),最坏的情况是O(n^2)。
参考1