1.快速排序

核心思想:1.找一个关键元素(pivote),循环比较数组中的元素与关键元素的大小,小的放左边,大的放右边。将左右两边两个小数组再递归以上操作,知道拆分的小数组中的元素小于2个,退出递归。2.在指定关键元素的时候可以简单的指定每次数组的最后一个元素,或者可以使用随机(可以达到期望值最佳,时间复杂度的期望值能达到O(nlogn))。

function quick_sort(nums) {
    random_partition(nums);
    return nums;
}

function random_partition(nums, l, r) {
    if(l >= r) return;
    let m = Math.floor(Math.random() *(r-l+1))+1;
    swap(nums, m, r);
    partition(nums, l, r);
}

function partition(nums, l, r) {
    let pivote = nums[r];
    let i = l -1;
    for(let j = l; j < r; ++j) {
        if(nums[j] <= pivote) {
            swap(nums, ++i, j);
        }
    }
    swap(nums, ++i, r);
    random_partition(nums, l, i-1);
    random_partition(nums, i+1, r);
}

function swap(nums,    i, j) {
    let tmp = nums[i];
    nums[i] = nums[j];
    nums[j] = tmp;
}

2.堆排序

核心思想:使用最小堆,每次将堆顶元素弹出,循环此操作,最终得到一个升序数组。这个方法需要先将输入的数组元素创建一个最小堆,并在每次弹出堆顶元素后需要做一次重建堆的操作,来维持最小堆的性质。时间复杂度为O(nlogn)

function stack_sort(nums) {
    let minStack = new min_stack(nums);
    return minStack.min_sort();
}

class min_stack {
    construct(nums) {
        this.stack = nums;
        this.size = this.stack.length;
        this.build();
    }

    build() {
        for(let i = Math.floor(n/2) -1; i > -1; --i) {
            this.siftdown(i);
        }
    }

    siftdown(i) {
        let j = i*2+1;
        while(j < this.size) {
            if(j+1 < this.size && this.stack[j] > this.stack[j+1]) ++j;
            if(this.stack[i] > this.stack[j]) {
                let tmp = this.stack[i];
                this.stack[i] = this.stack[j];
                this.stack[j] = tmp;
            }
            i = j;
            j = i*2+1;
        } 
    }

    min_sort() {
        let ret = [];
        for(let i = this.size -1; i >= 0; --i) {
            ret.push(this.stack[0]);
            this.stack[0] = this.stack[i];
            this.size -= 1;
            this.siftdown(0);
        }
        return ret;
    }
}

3.归并排序

核心思想:将数组递归拆分成左右两边,分别做排序后在合并两边有序数组;最终达到这个数组有序排列。整体分为拆分和合并,合并过程与合并两个有序数组一样, 时间复杂度O(nlogn)

function merge_sort(nums, l, r) {
    if(l >= r) return;
    let mid = Math.floor((r-l)/2);
    merge_sort(nums, l, mid);
    merge_sort(nums, mid+1, r);
    let i = l, j = mid+1;
    let tmp = [];
    while(i <= mid && j <= r) {
        if(nums[i] < nums[j]) {
            tmp.push(nums[i++])
        } else {
            tmp.push(nums[j++])
        }
    }
    while(i <= mid) {
        tmp.push(nums[i++])
    }
    while(j <= r) {
        tmp.push(nums[j++])
    }
    
    for(let k = 0; k < r-l+1; ++k) {
        nums[k+l] = tmp[k];
    }
}

functon sort(nums) {
    merge_sort(nums, 0, nums.length-1);
    return nums;
}

牛刀杀鸡
3 声望0 粉丝