高级排序-快排

快排

var sortArray = function(nums) {
    // 快排
    return quickStart(nums,0,nums.length-1);
}
function quickStart(nums,left,right) {
    if(left<right) {
    let index = partition(nums,left,right);
    quickStart(nums,0,index);
    quickStart(nums,index+1,right);
    }
    return nums;
}
// 分区: 快慢指针
function partition(array,left,right) {
    let pvit = left;   // 选择最左侧作为基准值,可优化(最左侧可能一直是较小的数,以此作为基准值,导致递归树向一边倾斜)
    let index = left+1;
    for(let i=index;i<=right;i++) { // i 指向小于基准值的指针,其之前的元素均大于基准值。index 指向大于基准值的指针
        if(array[i]<array[pvit]) { 
            swap(array,index,i);
            index++;
        }
    }
    swap(array,pvit,index-1);
    return index-1;

}
// 交换数组中的元素
function swap(array,i,j) {
    let temp = array[i];
    array[i] = array[j];
    array[j] = temp;
}
// 分区:挖坑
function partition2(array,left,right) {
    let pivot = array[left]; // 左侧元素作为第一个坑,也是基准值
    while(left<right) {
        while(left<right&&array[right]>=pivot) { //在right移动过程中,>right 均大于基准值,<left 均小于基准值,=left 大于基准值 
            right--;
        }
        if(left<right) array[left] = array[right];
        while(left<right&&array[left]<=pivot) { //在left 移动过程中,<left 均小于基准值,>right 均大于基准值,=right 小于基准值 
            left++;
        }
        if(left<right) array[right] = array[left];
    }
    array[left] = pivot;                                    // 两元素相遇,相遇点也为坑位,此时坑位之后均大于基准值,坑位之前均小于基准值,坑位填入基准值即可
    return left;
}
// 分区:双指针
function partition3(array,left,right) {
    let pivot  = array[left]; //基准值选在左侧
    let low  = left;
    while(left<right) {
        while(left<right&&array[right]>=pivot) { // 右指针先动,i、j相遇在分界线的左侧;左指针先动,i、j相遇在分界线的右侧
            right--;
        }
        while(left<right&&array[left]<=pivot) {
            left++;
        }
        if(left>=right) break;
        swap(array,left,right);                           // i、j相遇,即数组完成了分区,只需要将基准值移至分界点即可
    }
    swap(array,low,left);
    return left;
    
}
// 当数组为有序序列时,由于基准值选在左侧,导致递归树倾斜,排序算法退化成O(N^2)。优化:随机选择一个数作为基准值
// 优化:
function quickStart(nums,left,right) {
    if(left<right) {
     let pivot = Math.floor(Math.random()*(right-left+1))+left; //随机值作为基准值
     swap(nums,left,pivot)         // 将随机值换到最左侧即可
    let index = partition(nums,left,right);
    quickStart(nums,0,index);
    quickStart(nums,index+1,right);
    }
    return nums;
}

 1. 进一步优化: 当随机值每次都是最小值或最大值也会导致递归树倾斜,此时采用三数限制,可完全避免递归树过于倾斜。见leetcode官方网站。
 2. 以上均是从小到大顺序排序,那么逆序该怎么修改代码?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值